{"openapi":"3.1.0","info":{"title":"Allure Connect API","version":"1.0.0","description":"REST API for managing SCORM 1.2/2004 packages, sessions, and CMI data.\n\n## Authentication\n\nAuthenticated requests accept the API key as `Authorization: Bearer <api_key>` (preferred) or `X-API-Key: <api_key>`. If both are present, Bearer wins. Partner keys use the `public_api` scope; product integrations may use `internal_product` or `admin`. Keys are minted as `ac_live_` (production) or `ac_test_` (sandbox).\n\n### Signed-in dashboard sessions\n\nThe dashboard's own screens may call these routes with the member's session and no API key. Such a request is not a credential in its own right; it is held to the member's role in the workspace:\n\n- A request that changes anything (every method but `GET` and `HEAD`) needs an active workspace **owner** or **admin**, and must come from the app's own origin. Otherwise the answer is `403 WORKSPACE_ADMIN_REQUIRED` or `403 CUSTOMER_ORIGIN_REQUIRED`, and nothing is written.\n- A read needs an active membership of the workspace, in any role (`403 WORKSPACE_ROLE_REQUIRED` otherwise). Learner skill records and evidence (`/api/v1/cale/subjects/**`, `/api/v1/graph/learners/**`) need an owner or admin; `GET /api/v1/usage/spend-cap` needs an owner, admin or billing member.\n- On the session run-time routes (`/api/v1/sessions/{sessionId}`, `/refresh-token`, `/start-over`) a launch token is the credential. A dashboard session stands in for it only for an active owner or admin; any other member is answered as a caller with no token (`401 AUTH_REQUIRED`).\n\nAPI keys and the Allure LMS service are not affected by any of this: they are answered by their scope and permissions, from any origin. A request that carries a credential the route accepts is that credential, whatever cookie rides along. An input the route does not accept as a credential (a launch token in the query string outside the session run-time routes, LMS service headers on a route that does not take the service token, a dispatch token in a JSON body) does not stop a cookie being resolved.\n\nA dashboard session speaks for the member's active workspace. A session request to the upload routes (`/api/v1/packages/upload-url`, `upload-sessions`, `upload`, `process`, `multipart/*`) or to `POST /api/v1/quick-publish` must say which workspace its page was opened for in `X-Connect-Session-Workspace`: without it the answer is `400 SESSION_WORKSPACE_REQUIRED`, and when it is not the workspace the session is using the answer is `409 SESSION_WORKSPACE_CHANGED`, before anything is written. On every other route that authenticates through the same API-key wrapper, a session request that states a workspace is held to it the same way. On the xAPI LRS (`/api/lrs/xapi/**`) a dashboard session that stores something (statements `POST` and `PUT`; `PUT`, `POST` and `DELETE` on state, activity profile and agent profile) must state it too and is refused the same way; a read there is never asked. Routes whose authority is not a principal (dispatch launch, launch-link validation, hosted content) and the learner run-time routes ignore it, with one exception: `PUT /api/v1/sessions/{sessionId}` made with a dashboard session and no launch token is refused when it states a workspace the session is not using. The header never selects or authorizes a workspace. API keys and the Allure LMS service are never asked for it and are unaffected by sending it.\n\nThe signed-in dashboard routes (`/api/customer/**`, tagged Customer) take no API key and are held to the same statement on every request that changes something (every method but `GET` and `HEAD`). It is checked after the member and the request's origin are, and before the route's own handler runs: without `X-Connect-Session-Workspace` the answer is `400 SESSION_WORKSPACE_REQUIRED`, and when it is not the workspace the session is using the answer is `409 SESSION_WORKSPACE_CHANGED`. In both cases nothing is changed. Each of those operations lists the header and the two answers below. On an operation that also accepts a workspace in its address (`?workspace=`, older spelling `?tenantId=`) the header is required only when the address names none: a request that names a workspace is authorized in that workspace, is not a write to the session's, and is not asked. Two operations are never asked: the workspace switch (`POST /api/customer/tenant/switch`), which names the workspace to make active, and `PATCH /api/customer/integration-incidents/{incidentId}`, which acts on one incident by its id. The upload limit check (`POST /api/customer/packages/upload-limit-preflight`) writes nothing and is conditional the other way: it is asked when its body names no workspace (`tenant_id`), and not when it names one, which it authorizes. The dashboard's own pages send the header on every write; it is the workspace the page was rendered for, so a tab left open across a workspace switch is refused instead of writing to the newly active workspace.\n\n`OPTIONS` counts as a change. The role is read from the workspace's member record on each request; a role changed in the identity provider can take up to five minutes to apply, or longer if its notification is missed.\n\n### Getting Your API Key\n\n1. Sign in to your account\n2. Navigate to [**Dashboard**](/dashboard) → [**Integrations**](/dashboard/integrations?tab=keys) → **API Keys**\n3. Click **\"New API key\"**\n4. Copy your key once (it won't be shown again!)\n\n### Using Your API Key\n\nInclude the API key in all requests (either form):\n\n```bash\ncurl -H \"Authorization: Bearer your-api-key\" https://app.allureconnect.com/api/v1/packages\n# or\ncurl -H \"X-API-Key: your-api-key\" https://app.allureconnect.com/api/v1/packages\n```\n\n## Rate Limiting\n\nUpload and process routes enforce per-tenant windows (defaults: upload-url **120**/60s, process **60**/60s). Those gated responses include `X-RateLimit-*` headers. There is no global read/write RPM table for every partner route.\n\nWhen a gated limit is exceeded, a `429 Too Many Requests` response is returned.\n\n## Error Handling\n\nAll errors follow a consistent format:\n\n```json\n{\n  \"error\": \"Human-readable error message\",\n  \"code\": \"MACHINE_READABLE_ERROR_CODE\",\n  \"details\": { /* Additional context */ }\n}\n```\n\nCommon error codes:\n- `API_KEY_REQUIRED`: API key is missing, invalid, revoked, in the wrong mode, or outside the route's allowed scopes\n- `SESSION_WORKSPACE_CHANGED`, `SESSION_WORKSPACE_REQUIRED`: a signed-in dashboard session whose request was made for a workspace the session is no longer using, or did not say which. Never returned to an API key\n- `WORKSPACE_ADMIN_REQUIRED`, `WORKSPACE_ROLE_REQUIRED`, `CUSTOMER_ORIGIN_REQUIRED`: a signed-in dashboard session without the workspace role the request needs, or from another origin. Never returned to an API key\n- `TENANT_MISMATCH`: Requested tenant doesn't match API key\n- `VERSION_CONFLICT`: Optimistic locking conflict (retry required)\n- `RATE_LIMIT_EXCEEDED`: Too many requests\n- `VALIDATION_ERROR`: Request validation failed\n- `NOT_FOUND`: Resource not found\n- `QUOTA_EXCEEDED`: Storage or usage quota exceeded\n- `BACKEND_UNAVAILABLE`: Transient backend-capacity or transport failure. Retry after the `Retry-After` delay\n\n## Versioning\n\nThe API follows semantic versioning. The current version is `v1`. Version is specified in the URL path (`/api/v1/`).\n\n## OpenAPI document\n\n- Raw JSON: `GET /api/docs/openapi` (same host as the app)\n- Interactive explorer: `/api/docs` (Scalar UI)\n\n## Support\n\nFor questions or issues:\n- Email: support@allureconnect.com\n- Documentation: https://www.allureconnect.com/docs\n- Help center: https://www.allureconnect.com/help","contact":{"name":"Allure Connect","email":"support@allureconnect.com","url":"https://www.allureconnect.com/docs"},"license":{"name":"Proprietary","url":"https://allureconnect.com/legal/terms"}},"servers":[{"url":"https://app.allureconnect.com","description":"Production (recommended — same host as the Connect app)"},{"url":"https://allureconnect.com","description":"Production (apex; redirects may apply)"},{"url":"http://localhost:3000","description":"Local development"}],"tags":[{"name":"Health","description":"Service health endpoints"},{"name":"Credentials","description":"API key validation and non-secret credential metadata"},{"name":"Packages","description":"SCORM package management. Large uploads use POST /api/v1/packages/upload-url, browser PUT to the presigned URL, then POST /api/v1/packages/process."},{"name":"Uploads","description":"Multipart, process, progress, and upload-limit helpers"},{"name":"Sessions","description":"Session launch, tracking, and CMI data"},{"name":"xAPI","description":"Experience API (xAPI) statements and analytics"},{"name":"LRS","description":"Native xAPI 1.0.x / 2.0 LRS endpoints"},{"name":"Dispatches","description":"SCORM dispatch service for external distribution"},{"name":"Intelligence","description":"Evidence-backed role briefs, structured extraction, and auditable feedback for authorized product clients"},{"name":"Organizations","description":"Account-level customer and organization attribution groups"},{"name":"Webhooks","description":"Webhook registration and event delivery"},{"name":"Quotas","description":"Quota usage and limits"},{"name":"CALE","description":"Reusable canonical skills, alignments, and verified outcome projections for client learning systems"},{"name":"Conversions","description":"PPTX-to-SCORM conversion jobs and quick-publish"},{"name":"Connectors","description":"Connector installation registry and lifecycle events"},{"name":"Graph","description":"Capability graph: skills, roles, learners, value models (internal_product/admin)"},{"name":"Capability","description":"Public-tier capability read surfaces"},{"name":"Create","description":"Allure Create internal publish surface (v1 + v2); app host only; not rewritten on api.allureconnect.com"},{"name":"Tenants","description":"Tenant-level configuration (player chrome)"},{"name":"Revenue","description":"Seller revenue ledger (paid plans)"},{"name":"Content","description":"Package content asset serving"},{"name":"VR","description":"VR package registration"},{"name":"SCORM","description":"Legacy SCORM compatibility API (prefer /api/v1/*)"},{"name":"Customer","description":"Signed-in dashboard APIs (Clerk session auth)"},{"name":"Admin","description":"Platform-admin console APIs (Clerk session + platform_admin role)"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"},"BearerApiKey":{"type":"http","scheme":"bearer","bearerFormat":"Connect API key","description":"Connect API key supplied as Authorization: Bearer <api_key>"},"LaunchToken":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Signed launch token issued by Allure Connect"},"ClerkSession":{"type":"apiKey","in":"cookie","name":"__session","description":"Clerk session cookie. Callers must be authenticated via the Connect dashboard."},"AdminSession":{"type":"apiKey","in":"cookie","name":"__session","description":"Clerk session cookie with platform_admin role. Only usable by Allure Connect platform admins."},"LrsAuth":{"type":"http","scheme":"basic","description":"HTTP Basic auth against the per-tenant LRS credential pair. All authenticated xAPI requests must also include `X-Experience-API-Version`."}},"responses":{"Unauthorized":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"schemas":{"ErrorResponse":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"UploadPlanLimitResponse":{"type":"object","required":["error","code","current_plan","max_upload_mb","limit_source","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["FILE_TOO_LARGE"]},"current_plan":{"type":"string"},"max_upload_mb":{"type":"number","description":"Effective ceiling: the lower of the deployment and current-plan limits."},"limit_source":{"type":"string","enum":["plan","platform"]},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_upload_mb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_upload_mb":{"type":"number"}},"additionalProperties":false}]}},"additionalProperties":false,"examples":{"currentPlatformCap":{"value":{"error":"File too large. This deployment currently supports uploads up to 500 MB. A plan upgrade will not increase this processing limit.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":500,"limit_source":"platform","suggested_plan":null}},"tierUpgradeWhenPlatformAllows":{"value":{"error":"File too large. Maximum upload size for your plan is 2048 MB. Growth supports uploads up to 5120 MB.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":2048,"limit_source":"plan","suggested_plan":{"tier":"professional","name":"Growth","max_upload_mb":5120}}}}},"StorageQuotaExceededResponse":{"type":"object","required":["error","code","current_plan","max_storage_gb","current_storage_gb","projected_storage_gb","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["STORAGE_QUOTA_EXCEEDED"]},"current_plan":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0},"current_storage_gb":{"type":"number","minimum":0},"projected_storage_gb":{"type":"number","minimum":0},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_storage_gb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0}},"additionalProperties":false}]}},"additionalProperties":false},"ScormPackage":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}},"PackageVersion":{"type":"object","required":["id","packageId","versionLabel","contentType","status","manifestVersion","uploadedAt","storageKey"],"properties":{"id":{"type":"string"},"packageId":{"type":"string"},"versionLabel":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["uploaded","processing","ready","failed"]},"manifestVersion":{"type":"string","nullable":true},"uploadedAt":{"type":"string","format":"date-time"},"storageKey":{"type":"string"},"manifestUrl":{"type":"string","nullable":true},"launchUrl":{"type":"string","nullable":true},"artifactUrl":{"type":"string","nullable":true},"artifactFilename":{"type":"string","nullable":true},"artifactMimeType":{"type":"string","nullable":true},"platformTarget":{"type":"string","nullable":true}}},"PackageListResponse":{"type":"object","required":["packages"],"properties":{"packages":{"type":"array","items":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"},"totalIsLowerBound":{"type":"boolean","description":"True when total is a bounded lower estimate rather than an exact count."}}}}},"ProcessPackageRequest":{"type":"object","required":["storage_path","original_filename"],"properties":{"storage_path":{"type":"string","description":"Storage path returned by the upload-url or multipart flow."},"original_filename":{"type":"string","description":"Original filename of the uploaded ZIP (used for display and error messages)."},"package_id":{"type":"string","pattern":"^[A-Za-z0-9_-]+$","maxLength":512,"description":"Desired package_id slug. Auto-generated when omitted."},"connector_installation_id":{"type":"string","format":"uuid"},"acquisition_source":{"type":"string","enum":["wordpress_org","github","in_app","partner"]},"validate_only":{"type":"boolean","description":"When true, validate without persisting a package record."},"tenant_id":{"type":"string","description":"Ignored — the API key tenant is used. Accepted for client compatibility only."},"uploaded_by":{"type":"string","description":"Ignored — set to the API key id by the route. Accepted for client compatibility only."}}},"ProcessPackageResponse":{"type":"object","required":["upload_id","manifest","file_size_bytes","storage_path"],"properties":{"upload_id":{"type":"string"},"validation_only":{"type":"boolean"},"manifest":{"type":"object","required":["title","version","launch_url","sco_count","description","duration"],"properties":{"title":{"type":"string"},"version":{"type":"string","enum":["1.2","2004"]},"launch_url":{"type":"string"},"sco_count":{"type":"integer","minimum":0},"activities":{"type":"array","items":{"type":"object","required":["id","title"],"properties":{"id":{"type":"string"},"title":{"type":"string"}}}},"description":{"type":"string"},"duration":{"type":"string"}}},"file_size_bytes":{"type":"number","minimum":0},"storage_path":{"type":"string"},"package":{"type":"object","required":["package_id","title","launch_url","version","current_revision"],"properties":{"package_id":{"type":"string"},"title":{"type":"string"},"launch_url":{"type":"string"},"version":{"type":"string","enum":["1.2","2004"]},"current_revision":{"type":"integer","minimum":1}}}}},"PackageDetailResponse":{"type":"object","required":["package","versions"],"properties":{"package":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}},"versions":{"type":"array","items":{"type":"object","required":["id","packageId","versionLabel","contentType","status","manifestVersion","uploadedAt","storageKey"],"properties":{"id":{"type":"string"},"packageId":{"type":"string"},"versionLabel":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["uploaded","processing","ready","failed"]},"manifestVersion":{"type":"string","nullable":true},"uploadedAt":{"type":"string","format":"date-time"},"storageKey":{"type":"string"},"manifestUrl":{"type":"string","nullable":true},"launchUrl":{"type":"string","nullable":true},"artifactUrl":{"type":"string","nullable":true},"artifactFilename":{"type":"string","nullable":true},"artifactMimeType":{"type":"string","nullable":true},"platformTarget":{"type":"string","nullable":true}}}}}},"Organization":{"type":"object","required":["id","externalId","name","kind","status","createdAt","updatedAt"],"properties":{"id":{"type":"string","description":"Public organization identifier."},"externalId":{"type":"string","description":"Alias of id for forward compatibility."},"name":{"type":"string"},"kind":{"type":"string","enum":["internal","external"]},"status":{"type":"string","enum":["active","archived"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"OrganizationsResponse":{"type":"object","required":["organizations"],"properties":{"organizations":{"type":"array","items":{"type":"object","required":["id","externalId","name","kind","status","createdAt","updatedAt"],"properties":{"id":{"type":"string","description":"Public organization identifier."},"externalId":{"type":"string","description":"Alias of id for forward compatibility."},"name":{"type":"string"},"kind":{"type":"string","enum":["internal","external"]},"status":{"type":"string","enum":["active","archived"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}},"PackageMetadataUpdate":{"type":"object","properties":{"tenant_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"duration":{"type":"string","nullable":true},"sco_count":{"type":"integer","nullable":true},"tags":{"type":"array","items":{"type":"string"},"maxItems":20},"custom_metadata":{"type":"object","additionalProperties":true}},"description":"At least one metadata field must be provided."},"LaunchRequest":{"type":"object","required":["user_id"],"properties":{"user_id":{"type":"string","description":"Identifier of the learner launching the package"},"session_id":{"type":"string","format":"uuid","nullable":true,"description":"Existing session to resume (optional)"},"learner_activity":{"type":"string","enum":["foreground_v1"],"description":"Explicit hosted learner foreground capture, requiring exclusive SCORM. Omit for author preview. Captures trusted visible input only, with signed immutable session.foreground_activity events; never infer activity from CMI or polling."},"runtime_protocol":{"type":"string","enum":["exclusive_v1"],"description":"Opt in to exclusive runtime ownership. Omission preserves legacy hosted/partner writes for new sessions and never downgrades an opted-in session. Scoped session reuse may upgrade this policy without resetting progress; new attempts retain it."},"new_attempt":{"type":"boolean","description":"Retake: start a fresh attempt on the existing `session_id` (fresh status, score, suspend data and time). Earlier attempts stay in `attempt_history` and reports. A repeated call while the new attempt is untouched reuses it. Without it, relaunching a completed session follows the course setting `completedRelaunchBehavior`: `resume` for courses created before the setting existed, `review` for new courses."},"player_options":{"type":"object","properties":{"show_chrome":{"type":"boolean"},"auto_complete_on_exit":{"type":"boolean"},"open_in_new_window":{"type":"boolean"}},"additionalProperties":false}}},"LaunchResponse":{"type":"object","required":["package_id","session_id","launch_url","learner_id","content_type","storage_backend","expires_in_seconds"],"properties":{"package_id":{"type":"string","description":"Package identifier (e.g. pkg_…)"},"session_id":{"type":"string","format":"uuid"},"launch_url":{"type":"string","format":"uri","description":"Hosted player URL with signed session token in `?token=`. Embed as-is; do not strip query parameters."},"learner_id":{"type":"string","description":"Learner identifier from the launch request (`user_id`)."},"content_type":{"type":"string","enum":["scorm","vr_apk"]},"storage_backend":{"type":"string","enum":["r2","disabled"]},"expires_in_seconds":{"type":"integer","description":"Effective session token TTL after platform min/max clamping."},"attempt_number":{"type":"integer","minimum":1,"description":"Current attempt number for this session."}}},"ScormSession":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"attempts":{"type":"integer","nullable":true,"description":"Current attempt number (alias of `attempt_number`)."},"attempt_number":{"type":"integer","minimum":1,"description":"Current attempt number; status, score and time describe this attempt."},"launch_mode":{"type":"string","enum":["normal","review"],"description":"`review` when the hosted player opens a completed attempt read-only (cmi.mode=review)."},"start_over_allowed":{"type":"boolean","description":"Whether the hosted player offers \"Start over\" for the current attempt."},"attempt_history":{"type":"array","description":"Session detail only: up to 20 attempts, newest first. Earlier attempts keep their results after a retake or reset.","items":{"type":"object","properties":{"attempt_number":{"type":"integer"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","additionalProperties":true},"time_spent_seconds":{"type":"number"},"progress_percent":{"type":"number"},"started_at":{"type":"string","format":"date-time"},"last_activity_at":{"type":"string","format":"date-time"},"superseded_at":{"type":"string","format":"date-time","nullable":true},"superseded_reason":{"type":"string","nullable":true,"enum":["learner_start_over","launch_new_attempt","relaunch_policy","dashboard_reset","api_reset",null]}}}},"cmi_data":{"type":"object","additionalProperties":true},"suspend_data":{"type":"string","nullable":true},"version":{"type":"integer","minimum":1,"description":"Optimistic-locking revision. Increments on each committed update; pass the latest value back as `version` in PUT to detect concurrent writes."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","nullable":true}}},"SessionListResponse":{"type":"object","properties":{"sessions":{"type":"array","items":{"allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"attempts":{"type":"integer","nullable":true,"description":"Current attempt number (alias of `attempt_number`)."},"attempt_number":{"type":"integer","minimum":1,"description":"Current attempt number; status, score and time describe this attempt."},"launch_mode":{"type":"string","enum":["normal","review"],"description":"`review` when the hosted player opens a completed attempt read-only (cmi.mode=review)."},"start_over_allowed":{"type":"boolean","description":"Whether the hosted player offers \"Start over\" for the current attempt."},"attempt_history":{"type":"array","description":"Session detail only: up to 20 attempts, newest first. Earlier attempts keep their results after a retake or reset.","items":{"type":"object","properties":{"attempt_number":{"type":"integer"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","additionalProperties":true},"time_spent_seconds":{"type":"number"},"progress_percent":{"type":"number"},"started_at":{"type":"string","format":"date-time"},"last_activity_at":{"type":"string","format":"date-time"},"superseded_at":{"type":"string","format":"date-time","nullable":true},"superseded_reason":{"type":"string","nullable":true,"enum":["learner_start_over","launch_new_attempt","relaunch_policy","dashboard_reset","api_reset",null]}}}},"cmi_data":{"type":"object","additionalProperties":true},"suspend_data":{"type":"string","nullable":true},"version":{"type":"integer","minimum":1,"description":"Optimistic-locking revision. Increments on each committed update; pass the latest value back as `version` in PUT to detect concurrent writes."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","nullable":true}}},{"type":"object","properties":{"package":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}}}}]}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"hasMore":{"type":"boolean"},"total_is_lower_bound":{"type":"boolean","description":"True only when the safety read ceiling was reached and total is a lower bound."},"totalIsLowerBound":{"type":"boolean"},"page":{"type":"integer","deprecated":true,"description":"Compatibility alias derived from offset and limit."},"total_pages":{"type":"integer","deprecated":true,"description":"Compatibility alias. This is also a lower bound when total_is_lower_bound is true."},"has_next":{"type":"boolean","deprecated":true,"description":"Compatibility alias for has_more."},"has_prev":{"type":"boolean","deprecated":true,"description":"Compatibility alias indicating offset is greater than zero."}}}}},"ScormInteractionReport":{"type":"object","description":"Bounded read-only projection of retained CMI, not full attempt history or skill/mastery evidence. No new data is persisted. package_version and sco_id are unknown; reported_scorm_version is active-package metadata and is not historical provenance. Raw answer fields are sensitive learner data.","properties":{"schema_version":{"type":"integer","enum":[1]},"source":{"type":"string","enum":["retained_cmi_snapshot"]},"status":{"type":"string","enum":["available","empty","partial","unavailable"]},"scope":{"type":"object","properties":{"session_id":{"type":"string"},"package_id":{"type":"string"},"package_version":{"type":["string","null"],"description":"Always null: historical package version is not established by retained CMI."},"sco_id":{"type":["string","null"],"description":"Always null: a flattened session snapshot does not establish a SCO boundary."},"session_revision":{"type":"integer"},"reported_scorm_version":{"type":["string","null"],"enum":["1.2","2004",null]}}},"declared_count":{"type":["integer","null"]},"returned_count":{"type":"integer","maximum":200},"issues":{"type":"array","items":{"type":"string"},"description":"Partial/ambiguous data and bounds are explicit. Missing count is unknown, not proof of completeness."},"items":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"index":{"type":"integer"},"id":{"type":["string","null"]},"type":{"type":["string","null"]},"description":{"type":["string","null"],"maxLength":4096,"description":"Retained question description, normally supplied by SCORM2004; preserved regardless of current package metadata. Null for missing or oversized text. No question-bank inference."},"response":{"type":["string","null"],"description":"Empty answer is preserved. Conflicting SCORM aliases return null."},"result":{"type":"string","enum":["correct","incorrect","neutral","unanticipated","numeric","unknown"]},"result_raw":{"type":["string","null"]},"numeric_result":{"type":["number","null"]},"weighting":{"type":["number","null"]},"time_raw":{"type":["string","null"]},"latency_raw":{"type":["string","null"]},"evidence_classification":{"type":"string","enum":["unclassified"],"description":"No assessment/practice intent, mastery or credit inferred."}}}}}},"SessionDetailResponse":{"type":"object","properties":{"interaction_report":{"type":"object","description":"Bounded read-only projection of retained CMI, not full attempt history or skill/mastery evidence. No new data is persisted. package_version and sco_id are unknown; reported_scorm_version is active-package metadata and is not historical provenance. Raw answer fields are sensitive learner data.","properties":{"schema_version":{"type":"integer","enum":[1]},"source":{"type":"string","enum":["retained_cmi_snapshot"]},"status":{"type":"string","enum":["available","empty","partial","unavailable"]},"scope":{"type":"object","properties":{"session_id":{"type":"string"},"package_id":{"type":"string"},"package_version":{"type":["string","null"],"description":"Always null: historical package version is not established by retained CMI."},"sco_id":{"type":["string","null"],"description":"Always null: a flattened session snapshot does not establish a SCO boundary."},"session_revision":{"type":"integer"},"reported_scorm_version":{"type":["string","null"],"enum":["1.2","2004",null]}}},"declared_count":{"type":["integer","null"]},"returned_count":{"type":"integer","maximum":200},"issues":{"type":"array","items":{"type":"string"},"description":"Partial/ambiguous data and bounds are explicit. Missing count is unknown, not proof of completeness."},"items":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"index":{"type":"integer"},"id":{"type":["string","null"]},"type":{"type":["string","null"]},"description":{"type":["string","null"],"maxLength":4096,"description":"Retained question description, normally supplied by SCORM2004; preserved regardless of current package metadata. Null for missing or oversized text. No question-bank inference."},"response":{"type":["string","null"],"description":"Empty answer is preserved. Conflicting SCORM aliases return null."},"result":{"type":"string","enum":["correct","incorrect","neutral","unanticipated","numeric","unknown"]},"result_raw":{"type":["string","null"]},"numeric_result":{"type":["number","null"]},"weighting":{"type":["number","null"]},"time_raw":{"type":["string","null"]},"latency_raw":{"type":["string","null"]},"evidence_classification":{"type":"string","enum":["unclassified"],"description":"No assessment/practice intent, mastery or credit inferred."}}}}}},"session":{"allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"attempts":{"type":"integer","nullable":true,"description":"Current attempt number (alias of `attempt_number`)."},"attempt_number":{"type":"integer","minimum":1,"description":"Current attempt number; status, score and time describe this attempt."},"launch_mode":{"type":"string","enum":["normal","review"],"description":"`review` when the hosted player opens a completed attempt read-only (cmi.mode=review)."},"start_over_allowed":{"type":"boolean","description":"Whether the hosted player offers \"Start over\" for the current attempt."},"attempt_history":{"type":"array","description":"Session detail only: up to 20 attempts, newest first. Earlier attempts keep their results after a retake or reset.","items":{"type":"object","properties":{"attempt_number":{"type":"integer"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","additionalProperties":true},"time_spent_seconds":{"type":"number"},"progress_percent":{"type":"number"},"started_at":{"type":"string","format":"date-time"},"last_activity_at":{"type":"string","format":"date-time"},"superseded_at":{"type":"string","format":"date-time","nullable":true},"superseded_reason":{"type":"string","nullable":true,"enum":["learner_start_over","launch_new_attempt","relaunch_policy","dashboard_reset","api_reset",null]}}}},"cmi_data":{"type":"object","additionalProperties":true},"suspend_data":{"type":"string","nullable":true},"version":{"type":"integer","minimum":1,"description":"Optimistic-locking revision. Increments on each committed update; pass the latest value back as `version` in PUT to detect concurrent writes."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","nullable":true}}},{"type":"object","properties":{"runtimeProtocol":{"type":"string","enum":["legacy","exclusive_v1"],"description":"Server launch policy; only exclusive_v1 sessions may claim a runtime."},"runtimeOwnerId":{"type":"string","format":"uuid","nullable":true,"description":"Current attempt runtime owner, or null before any claim."},"package":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}},"tenant":{"type":"object","description":"Tenant profile metadata","additionalProperties":true},"preferences":{"type":"object","additionalProperties":true}}}]},"preferences":{"type":"object","additionalProperties":true}}},"SessionRuntimeClaimRequest":{"type":"object","additionalProperties":false,"required":["runtime_id","expected_runtime_id","attempt"],"properties":{"runtime_id":{"type":"string","format":"uuid","description":"Fresh identity for this browser runtime; reuse only for retries of this claim."},"expected_runtime_id":{"type":"string","format":"uuid","nullable":true,"description":"Owner returned by GET session.runtimeOwnerId; null when never claimed."},"attempt":{"type":"integer","minimum":1}}},"SessionUpdateRequest":{"type":"object","properties":{"runtime_id":{"type":"string","format":"uuid","description":"Required with attempt for every write after a runtime claim, including unload; a superseded or review writer is rejected."},"cmi_data":{"type":"object","additionalProperties":true},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":0,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"session_time":{"type":"string","description":"ISO 8601 duration, e.g., PT35M42S"},"suspend_data":{"type":"string"},"attempt":{"type":"integer","minimum":1,"description":"Optional. The attempt number the writer loaded. If a retake or reset has replaced it, the write fails with 409 ATTEMPT_SUPERSEDED instead of touching the new attempt. Completed/passed never regresses within an attempt; start a new attempt to let a learner redo the course."},"version":{"type":"integer","minimum":1,"description":"Optional expected revision. A stale revision returns 409 VERSION_CONFLICT. Omitting version skips only revision comparison; it never bypasses runtime ownership or attempt fencing. Claimed-session unload writes still require matching runtime_id and attempt. Never rebase or retry writes after RUNTIME_SUPERSEDED or ATTEMPT_SUPERSEDED."}}},"SessionUpdateResponse":{"type":"object","description":"Write confirmation plus the full post-write session. The canonical representation is the nested `session` object; the snake_case root fields mirror it as compatibility aliases for SCORM/LMS adapters. Either way a client can persist the result of a PUT without a follow-up GET.","properties":{"success":{"type":"boolean"},"session_id":{"type":"string","format":"uuid"},"updated_at":{"type":"string","format":"date-time"},"session":{"type":"object","additionalProperties":true,"description":"Canonical post-write session in the camelCase player shape (`cmiData`, `suspendData`, `completionStatus`, `timeSpentSeconds`, …). Read `session.version` for the revision to send on the next PUT.","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"integer","minimum":1,"description":"Revision after this write. Pass as `version` on the next PUT."}}},"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"learner_id":{"type":"string","description":"Alias of `user_id`."},"learner_name":{"type":"string","nullable":true},"status":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"progress_percent":{"type":"number","nullable":true},"progress":{"type":"number","nullable":true,"description":"Alias of `progress_percent` (0–100) for LMS adapters that read `progress`."},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"cmi_data":{"type":"object","additionalProperties":true},"cmi":{"type":"object","additionalProperties":true,"description":"Alias of `cmi_data` for LMS adapters that expect `cmi`."},"suspend_data":{"type":"string","nullable":true},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"time_spent_seconds":{"type":"integer","nullable":true},"time_seconds":{"type":"integer","nullable":true,"description":"Alias of `time_spent_seconds`."},"attempts":{"type":"integer","nullable":true},"version":{"type":"integer","minimum":1,"description":"Revision after this write. Pass it as `version` on the next PUT."},"launch_url":{"type":"string","format":"uri","nullable":true},"manifest_url":{"type":"string","format":"uri","nullable":true},"created_at":{"type":"string","format":"date-time"},"lesson_location":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.lesson_location` / `cmi.location`."},"entry":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.entry` / `cmi.entry`."},"exit":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.exit` / `cmi.exit`."},"scorm_version":{"type":"string","nullable":true}}},"SessionTokenRefreshResponse":{"type":"object","required":["success","session_id","token","expires_in_seconds","launch_url"],"properties":{"success":{"type":"boolean"},"session_id":{"type":"string","format":"uuid"},"token":{"type":"string","description":"Fresh bearer token for the same SCORM session."},"expires_in_seconds":{"type":"integer","description":"Effective token TTL after platform min/max clamping."},"launch_url":{"type":"string","format":"uri","description":"Hosted player URL for this session with the fresh token already in `?token=`. LMS reopen must embed this URL (or relaunch with `session_id`); do not load package `launcher.html` as a substitute."}}},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","unhealthy"]},"service":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"checks":{"type":"object","properties":{"database":{"type":"boolean"}}},"error":{"type":"string","nullable":true}}},"XAPIActor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"XAPIVerb":{"type":"object","required":["id"],"description":"xAPI Verb","properties":{"id":{"type":"string","format":"uri","description":"Verb IRI"},"display":{"type":"object","description":"Language map for verb display","additionalProperties":{"type":"string"}}}},"XAPIActivity":{"type":"object","required":["id"],"description":"xAPI Activity Object","properties":{"objectType":{"type":"string","enum":["Activity"]},"id":{"type":"string","format":"uri","description":"Activity IRI"},"definition":{"type":"object","properties":{"name":{"type":"object","additionalProperties":{"type":"string"}},"description":{"type":"object","additionalProperties":{"type":"string"}},"type":{"type":"string","format":"uri"},"moreInfo":{"type":"string","format":"uri"},"extensions":{"type":"object","additionalProperties":true}}}}},"XAPIResult":{"type":"object","description":"xAPI Result","properties":{"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":-1,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"success":{"type":"boolean"},"completion":{"type":"boolean"},"response":{"type":"string"},"duration":{"type":"string","description":"ISO 8601 duration"},"extensions":{"type":"object","additionalProperties":true}}},"XAPIContext":{"type":"object","description":"xAPI Context","properties":{"registration":{"type":"string","format":"uuid"},"instructor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"team":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"platform":{"type":"string"},"language":{"type":"string"},"extensions":{"type":"object","additionalProperties":true}}},"XAPIStatement":{"type":"object","required":["actor","verb","object"],"description":"xAPI Statement (Experience API 1.0.3)","properties":{"id":{"type":"string","description":"Caller-supplied statement identifier or generated UUID."},"actor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"verb":{"type":"object","required":["id"],"description":"xAPI Verb","properties":{"id":{"type":"string","format":"uri","description":"Verb IRI"},"display":{"type":"object","description":"Language map for verb display","additionalProperties":{"type":"string"}}}},"object":{"type":"object","required":["id"],"description":"xAPI Activity Object","properties":{"objectType":{"type":"string","enum":["Activity"]},"id":{"type":"string","format":"uri","description":"Activity IRI"},"definition":{"type":"object","properties":{"name":{"type":"object","additionalProperties":{"type":"string"}},"description":{"type":"object","additionalProperties":{"type":"string"}},"type":{"type":"string","format":"uri"},"moreInfo":{"type":"string","format":"uri"},"extensions":{"type":"object","additionalProperties":true}}}}},"result":{"type":"object","description":"xAPI Result","properties":{"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":-1,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"success":{"type":"boolean"},"completion":{"type":"boolean"},"response":{"type":"string"},"duration":{"type":"string","description":"ISO 8601 duration"},"extensions":{"type":"object","additionalProperties":true}}},"context":{"type":"object","description":"xAPI Context","properties":{"registration":{"type":"string","format":"uuid"},"instructor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"team":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"platform":{"type":"string"},"language":{"type":"string"},"extensions":{"type":"object","additionalProperties":true}}},"timestamp":{"type":"string","format":"date-time"},"stored":{"type":"string","format":"date-time"},"authority":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"version":{"type":"string","enum":["1.0.0","1.0.1","1.0.2","1.0.3"]}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","actor":{"name":"John Doe","mbox":"mailto:john@example.com"},"verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"en-US":"completed"}},"object":{"id":"https://allureconnect.com/packages/abc-123","definition":{"name":{"en-US":"Introduction to JavaScript"},"type":"http://adlnet.gov/expapi/activities/course"}},"result":{"score":{"scaled":0.95,"raw":95,"min":0,"max":100},"success":true,"completion":true,"duration":"PT1H30M"},"timestamp":"2025-01-01T12:00:00Z"}},"XAPIStatementsResponse":{"type":"object","required":["statements","pagination"],"properties":{"statements":{"type":"array","items":{"type":"object","required":["actor","verb","object"],"description":"xAPI Statement (Experience API 1.0.3)","properties":{"id":{"type":"string","description":"Caller-supplied statement identifier or generated UUID."},"actor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"verb":{"type":"object","required":["id"],"description":"xAPI Verb","properties":{"id":{"type":"string","format":"uri","description":"Verb IRI"},"display":{"type":"object","description":"Language map for verb display","additionalProperties":{"type":"string"}}}},"object":{"type":"object","required":["id"],"description":"xAPI Activity Object","properties":{"objectType":{"type":"string","enum":["Activity"]},"id":{"type":"string","format":"uri","description":"Activity IRI"},"definition":{"type":"object","properties":{"name":{"type":"object","additionalProperties":{"type":"string"}},"description":{"type":"object","additionalProperties":{"type":"string"}},"type":{"type":"string","format":"uri"},"moreInfo":{"type":"string","format":"uri"},"extensions":{"type":"object","additionalProperties":true}}}}},"result":{"type":"object","description":"xAPI Result","properties":{"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":-1,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"success":{"type":"boolean"},"completion":{"type":"boolean"},"response":{"type":"string"},"duration":{"type":"string","description":"ISO 8601 duration"},"extensions":{"type":"object","additionalProperties":true}}},"context":{"type":"object","description":"xAPI Context","properties":{"registration":{"type":"string","format":"uuid"},"instructor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"team":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"platform":{"type":"string"},"language":{"type":"string"},"extensions":{"type":"object","additionalProperties":true}}},"timestamp":{"type":"string","format":"date-time"},"stored":{"type":"string","format":"date-time"},"authority":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"version":{"type":"string","enum":["1.0.0","1.0.1","1.0.2","1.0.3"]}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","actor":{"name":"John Doe","mbox":"mailto:john@example.com"},"verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"en-US":"completed"}},"object":{"id":"https://allureconnect.com/packages/abc-123","definition":{"name":{"en-US":"Introduction to JavaScript"},"type":"http://adlnet.gov/expapi/activities/course"}},"result":{"score":{"scaled":0.95,"raw":95,"min":0,"max":100},"success":true,"completion":true,"duration":"PT1H30M"},"timestamp":"2025-01-01T12:00:00Z"}}},"pagination":{"type":"object","required":["page","limit","total","totalPages"],"properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"truncated":{"type":"boolean","description":"True when the result reflects only a bounded most-recent slice (up to 10,000 raw rows / 8 MiB). Totals then describe that slice, not the complete tenant history; follow nextCursor for the rest. Private learner rows are excluded."},"nextCursor":{"type":["string","null"],"description":"Sealed continuation: it cannot be read or altered, and it is valid only for the workspace and the filters of the request that returned it. Pass it back as the cursor query parameter to read the next page; null means there is nothing more to read. A page may hold fewer statements than limit (even none) while nextCursor is still set."}}}}},"ActorPerformance":{"type":"object","description":"Aggregated performance metrics by actor","properties":{"tenant_id":{"type":"string","format":"uuid"},"actor_mbox":{"type":"string","format":"email"},"actor_name":{"type":"string"},"total_statements":{"type":"integer"},"unique_activities":{"type":"integer"},"completed_count":{"type":"integer"},"passed_count":{"type":"integer"},"failed_count":{"type":"integer"},"success_count":{"type":"integer"},"completion_count":{"type":"integer"},"avg_score_scaled":{"type":"number","nullable":true},"scored_count":{"type":"integer","description":"Number of statements behind avg_score_scaled."},"first_activity":{"type":"string","format":"date-time"},"last_activity":{"type":"string","format":"date-time"}}},"ActivityPerformance":{"type":"object","description":"Aggregated performance metrics by activity","properties":{"tenant_id":{"type":"string","format":"uuid"},"activity_id":{"type":"string","format":"uri"},"activity_type":{"type":"string","format":"uri","nullable":true},"package_id":{"type":"string","format":"uuid","nullable":true},"total_statements":{"type":"integer"},"unique_learners":{"type":"integer"},"completed_count":{"type":"integer"},"passed_count":{"type":"integer"},"failed_count":{"type":"integer"},"success_count":{"type":"integer"},"completion_count":{"type":"integer"},"avg_score_scaled":{"type":"number","nullable":true},"scored_count":{"type":"integer","description":"Number of statements behind avg_score_scaled."},"first_activity":{"type":"string","format":"date-time"},"last_activity":{"type":"string","format":"date-time"}}},"CaleLearningResourceRef":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"CaleOutcomeSubjectRef":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"CaleClientSystem":{"type":"object","additionalProperties":false,"required":["id","kind","name","status"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["lms","authoring_platform","assessment_platform","learning_application","other"]},"name":{"type":"string"},"status":{"type":"string","enum":["active","disabled"]},"reserved":{"type":"boolean"},"subjectIdentity":{"type":"string","enum":["runtime_learner_ref"],"description":"Present when this system's subjectRef is the learner ref it launches with, so learner-skill reads and evidence from the LMS service and `internal_product`/`admin` callers address the learner's runtime record. `public_api` keys keep client-scoped subjects."}}},"CaleGraphRevision":{"type":"object","additionalProperties":false,"required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"CaleSkill":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"CaleFramework":{"type":"object","additionalProperties":false,"required":["id","name","version","status","checksum","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"version":{"type":"string"},"status":{"type":"string","enum":["active","deprecated","retired"]},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"updatedAt":{"type":"string","format":"date-time"},"skills":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}},"CaleAlignmentItem":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}},"CaleAlignmentValidation":{"type":"object","required":["ok","errors"],"properties":{"ok":{"type":"boolean"},"code":{"type":"string"},"errors":{"type":"array","items":{"type":"object","additionalProperties":true}},"canonical":{"type":"object","required":["resource","alignments"],"properties":{"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}}}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graph":{"type":"object","additionalProperties":false,"required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"policyRevision":{"type":"string"}}},"CaleAlignmentSet":{"type":"object","additionalProperties":false,"required":["id","resource","revision","checksum","graphRevision","graphChecksum","policyRevision","alignments","receipt","updatedAt"],"properties":{"id":{"type":"string"},"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graphRevision":{"type":"integer","minimum":1},"graphChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"policyRevision":{"type":"string"},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}},"receipt":{"type":"string","description":"ES256 compact JWS receipt."},"updatedAt":{"type":"string","format":"date-time"}}},"CaleLearnerProjection":{"type":"object","required":["subject","skillId"],"properties":{"subject":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"skillId":{"type":"string"},"skillVersion":{"type":"string"},"state":{"type":"string","enum":["unobserved","developing","verified","expired","revoked"]},"reasonCodes":{"type":"array","items":{"type":"string"}},"mastery":{"type":"number"},"confidence":{"type":"number"},"evidence":{"type":"object","additionalProperties":false,"required":["acceptedCount","assessmentCount","exposureCount","applied","quality"],"properties":{"acceptedCount":{"type":"integer","minimum":0},"assessmentCount":{"type":"integer","minimum":0},"exposureCount":{"type":"integer","minimum":0},"applied":{"type":"boolean"},"quality":{"type":"string","enum":["none","exposure_only","qualifying"]}}},"explanation":{"type":"object","description":"A line to show beside the level describing how many scored results stand behind it. This release stores no strongest demonstration fact.","required":["scoredResults","strongestEvidence","text"],"properties":{"scoredResults":{"type":"integer","minimum":0},"strongestEvidence":{"type":"null","description":"This release stores no strongest demonstration fact."},"text":{"type":"string","description":"For example: \"Based on 3 scored results.\""}}},"decayState":{"type":"string","enum":["current","decaying","lapsed"]},"lastDemonstratedAt":{"type":["string","null"],"format":"date-time"},"policyRevision":{"type":"string"},"sourceRevision":{"type":"integer","minimum":1},"sourceChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"observedAt":{"type":"string","format":"date-time"},"validUntil":{"type":"string","format":"date-time"},"error":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","enum":["CLIENT_SYSTEM_NOT_FOUND","SKILL_NOT_FOUND"]}}}},"oneOf":[{"required":["error"]},{"required":["skillVersion","state","reasonCodes","mastery","confidence","evidence","decayState","lastDemonstratedAt","policyRevision","sourceRevision","sourceChecksum","observedAt","validUntil"]}]},"CaleCapabilitiesResponse":{"type":"object","additionalProperties":false,"required":["data","principal"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["contractVersion","graph","limits","projectionValiditySeconds","permissions","receipt"],"properties":{"contractVersion":{"type":"string"},"graph":{"type":"object","additionalProperties":false,"required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"limits":{"type":"object","additionalProperties":false,"required":["resolverReferences","graphRoots","graphDepth","graphNodes","alignmentSets","subjects","skills","projectionCells"],"properties":{"resolverReferences":{"type":"integer"},"graphRoots":{"type":"integer"},"graphDepth":{"type":"integer"},"graphNodes":{"type":"integer"},"alignmentSets":{"type":"integer"},"subjects":{"type":"integer"},"skills":{"type":"integer"},"projectionCells":{"type":"integer"}}},"projectionValiditySeconds":{"type":"integer"},"permissions":{"type":"array","items":{"type":"string","enum":["cale:graph:read","cale:alignments:write","cale:learner-skills:read","cale:evidence:write","cale:mappings:review"]}},"receipt":{"type":"object","additionalProperties":false,"required":["algorithm","format","jwksPath"],"properties":{"algorithm":{"const":"ES256"},"format":{"const":"compact-jws"},"jwksPath":{"type":"string"}}}}},"principal":{"type":"object","additionalProperties":false,"required":["permissions","clientSystemIds"],"properties":{"permissions":{"type":"array","items":{"type":"string"}},"clientSystemIds":{"type":["array","null"],"items":{"type":"string"}}}}}},"CaleClientSystemsResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","kind","name","status"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["lms","authoring_platform","assessment_platform","learning_application","other"]},"name":{"type":"string"},"status":{"type":"string","enum":["active","disabled"]},"reserved":{"type":"boolean"},"subjectIdentity":{"type":"string","enum":["runtime_learner_ref"],"description":"Present when this system's subjectRef is the learner ref it launches with, so learner-skill reads and evidence from the LMS service and `internal_product`/`admin` callers address the learner's runtime record. `public_api` keys keep client-scoped subjects."}}}}}},"CaleClientSystemResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","kind","name","status"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["lms","authoring_platform","assessment_platform","learning_application","other"]},"name":{"type":"string"},"status":{"type":"string","enum":["active","disabled"]},"reserved":{"type":"boolean"},"subjectIdentity":{"type":"string","enum":["runtime_learner_ref"],"description":"Present when this system's subjectRef is the learner ref it launches with, so learner-skill reads and evidence from the LMS service and `internal_product`/`admin` callers address the learner's runtime record. `public_api` keys keep client-scoped subjects."}}}}},"CaleFrameworksResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name","version","status","checksum","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"version":{"type":"string"},"status":{"type":"string","enum":["active","deprecated","retired"]},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"updatedAt":{"type":"string","format":"date-time"},"skills":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}},"CaleFrameworkResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","name","version","status","checksum","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"version":{"type":"string"},"status":{"type":"string","enum":["active","deprecated","retired"]},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"updatedAt":{"type":"string","format":"date-time"},"skills":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}},"CaleSkillsResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}},"CaleSkillResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}},"CaleSkillResolutionResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["reference","status"],"properties":{"reference":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","minLength":1},"alias":{"type":"string","minLength":1},"version":{"type":"string","minLength":1}},"anyOf":[{"required":["id"]},{"required":["alias"]}]},"status":{"type":"string","enum":["resolved","unknown","proposed","cross_tenant","deprecated","retired","version_conflict"]},"skillId":{"type":"string"},"canonicalVersion":{"type":"string"},"skill":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}},"CaleGraphResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["revision","checksum","nodes","edges","truncated","observedAt","validUntil"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"nodes":{"type":"array","maxItems":200,"items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}},"edges":{"type":"array","description":"Accepted links only. A `prerequisite` edge points from the prerequisite (`fromSkillId`) to the skill it unlocks (`toSkillId`). A `related` edge has no direction.","items":{"type":"object","additionalProperties":false,"required":["fromSkillId","toSkillId","type","weight"],"properties":{"fromSkillId":{"type":"string"},"toSkillId":{"type":"string"},"type":{"type":"string","enum":["prerequisite","related"]},"weight":{"type":["number","null"]}}}},"truncated":{"type":"boolean"},"observedAt":{"type":"string","format":"date-time"},"validUntil":{"type":"string","format":"date-time"}}}}},"CaleAlignmentValidationResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","required":["ok","errors"],"properties":{"ok":{"type":"boolean"},"code":{"type":"string"},"errors":{"type":"array","items":{"type":"object","additionalProperties":true}},"canonical":{"type":"object","required":["resource","alignments"],"properties":{"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}}}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graph":{"type":"object","additionalProperties":false,"required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"policyRevision":{"type":"string"}}}}},"CaleAlignmentSetResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","resource","revision","checksum","graphRevision","graphChecksum","policyRevision","alignments","receipt","updatedAt"],"properties":{"id":{"type":"string"},"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graphRevision":{"type":"integer","minimum":1},"graphChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"policyRevision":{"type":"string"},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}},"receipt":{"type":"string","description":"ES256 compact JWS receipt."},"updatedAt":{"type":"string","format":"date-time"}}}}},"CaleAlignmentSetsResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","resource","revision","checksum","graphRevision","graphChecksum","policyRevision","alignments","receipt","updatedAt"],"properties":{"id":{"type":"string"},"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graphRevision":{"type":"integer","minimum":1},"graphChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"policyRevision":{"type":"string"},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}},"receipt":{"type":"string","description":"ES256 compact JWS receipt."},"updatedAt":{"type":"string","format":"date-time"}}}}}},"CaleLearnerSkillsResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["projections"],"properties":{"projections":{"type":"array","maxItems":5000,"items":{"type":"object","required":["subject","skillId"],"properties":{"subject":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"skillId":{"type":"string"},"skillVersion":{"type":"string"},"state":{"type":"string","enum":["unobserved","developing","verified","expired","revoked"]},"reasonCodes":{"type":"array","items":{"type":"string"}},"mastery":{"type":"number"},"confidence":{"type":"number"},"evidence":{"type":"object","additionalProperties":false,"required":["acceptedCount","assessmentCount","exposureCount","applied","quality"],"properties":{"acceptedCount":{"type":"integer","minimum":0},"assessmentCount":{"type":"integer","minimum":0},"exposureCount":{"type":"integer","minimum":0},"applied":{"type":"boolean"},"quality":{"type":"string","enum":["none","exposure_only","qualifying"]}}},"explanation":{"type":"object","description":"A line to show beside the level describing how many scored results stand behind it. This release stores no strongest demonstration fact.","required":["scoredResults","strongestEvidence","text"],"properties":{"scoredResults":{"type":"integer","minimum":0},"strongestEvidence":{"type":"null","description":"This release stores no strongest demonstration fact."},"text":{"type":"string","description":"For example: \"Based on 3 scored results.\""}}},"decayState":{"type":"string","enum":["current","decaying","lapsed"]},"lastDemonstratedAt":{"type":["string","null"],"format":"date-time"},"policyRevision":{"type":"string"},"sourceRevision":{"type":"integer","minimum":1},"sourceChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"observedAt":{"type":"string","format":"date-time"},"validUntil":{"type":"string","format":"date-time"},"error":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","enum":["CLIENT_SYSTEM_NOT_FOUND","SKILL_NOT_FOUND"]}}}},"oneOf":[{"required":["error"]},{"required":["skillVersion","state","reasonCodes","mastery","confidence","evidence","decayState","lastDemonstratedAt","policyRevision","sourceRevision","sourceChecksum","observedAt","validUntil"]}]}}}}}},"CaleEvidenceBatchResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["results"],"properties":{"results":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["evidenceId","disposition"],"properties":{"evidenceId":{"type":"string"},"disposition":{"type":"string","enum":["accepted","duplicate","rejected","quarantined"]},"reasonCode":{"type":"string"}}}}}}}},"CaleLearnerProjectionResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","required":["subject","skillId"],"properties":{"subject":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"skillId":{"type":"string"},"skillVersion":{"type":"string"},"state":{"type":"string","enum":["unobserved","developing","verified","expired","revoked"]},"reasonCodes":{"type":"array","items":{"type":"string"}},"mastery":{"type":"number"},"confidence":{"type":"number"},"evidence":{"type":"object","additionalProperties":false,"required":["acceptedCount","assessmentCount","exposureCount","applied","quality"],"properties":{"acceptedCount":{"type":"integer","minimum":0},"assessmentCount":{"type":"integer","minimum":0},"exposureCount":{"type":"integer","minimum":0},"applied":{"type":"boolean"},"quality":{"type":"string","enum":["none","exposure_only","qualifying"]}}},"explanation":{"type":"object","description":"A line to show beside the level describing how many scored results stand behind it. This release stores no strongest demonstration fact.","required":["scoredResults","strongestEvidence","text"],"properties":{"scoredResults":{"type":"integer","minimum":0},"strongestEvidence":{"type":"null","description":"This release stores no strongest demonstration fact."},"text":{"type":"string","description":"For example: \"Based on 3 scored results.\""}}},"decayState":{"type":"string","enum":["current","decaying","lapsed"]},"lastDemonstratedAt":{"type":["string","null"],"format":"date-time"},"policyRevision":{"type":"string"},"sourceRevision":{"type":"integer","minimum":1},"sourceChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"observedAt":{"type":"string","format":"date-time"},"validUntil":{"type":"string","format":"date-time"},"error":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","enum":["CLIENT_SYSTEM_NOT_FOUND","SKILL_NOT_FOUND"]}}}},"oneOf":[{"required":["error"]},{"required":["skillVersion","state","reasonCodes","mastery","confidence","evidence","decayState","lastDemonstratedAt","policyRevision","sourceRevision","sourceChecksum","observedAt","validUntil"]}]}}},"CaleEvidenceItem":{"type":"object","additionalProperties":false,"required":["evidenceId","source","outcome","delta","occurredAt","recordedAt","contentRef"],"properties":{"evidenceId":{"type":"string"},"source":{"type":"object","additionalProperties":false,"required":["clientSystemId","kind"],"properties":{"clientSystemId":{"type":"string"},"kind":{"type":"string","enum":["exposure","assessment","completion","human_approval"]}}},"outcome":{"type":"object","additionalProperties":false,"required":["disposition","reasonCode","scoreScaled","weight"],"properties":{"disposition":{"type":"string","enum":["accepted","duplicate","rejected","quarantined"]},"reasonCode":{"type":["string","null"]},"scoreScaled":{"type":["number","null"],"minimum":0,"maximum":1},"weight":{"type":["number","null"],"minimum":0,"maximum":1}}},"delta":{"type":"object","additionalProperties":false,"required":["exposureCount","assessmentCount","confidence","masteryCandidate"],"description":"What ingesting this item applied to the learner-skill state. Items that were not accepted apply nothing. `masteryCandidate` is the 0–100 mastery an accepted assessment offered; the state keeps the higher of it and its prior value.","properties":{"exposureCount":{"type":"integer","minimum":0,"maximum":1},"assessmentCount":{"type":"integer","minimum":0,"maximum":1},"confidence":{"type":"number","minimum":0},"masteryCandidate":{"type":["number","null"],"minimum":0,"maximum":100}}},"occurredAt":{"type":"string","format":"date-time"},"recordedAt":{"type":"string","format":"date-time"},"contentRef":{"anyOf":[{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},{"type":"null"}]}}},"CaleEvidenceLedgerResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["subject","skillId","items","page"],"properties":{"subject":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"skillId":{"type":"string"},"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["evidenceId","source","outcome","delta","occurredAt","recordedAt","contentRef"],"properties":{"evidenceId":{"type":"string"},"source":{"type":"object","additionalProperties":false,"required":["clientSystemId","kind"],"properties":{"clientSystemId":{"type":"string"},"kind":{"type":"string","enum":["exposure","assessment","completion","human_approval"]}}},"outcome":{"type":"object","additionalProperties":false,"required":["disposition","reasonCode","scoreScaled","weight"],"properties":{"disposition":{"type":"string","enum":["accepted","duplicate","rejected","quarantined"]},"reasonCode":{"type":["string","null"]},"scoreScaled":{"type":["number","null"],"minimum":0,"maximum":1},"weight":{"type":["number","null"],"minimum":0,"maximum":1}}},"delta":{"type":"object","additionalProperties":false,"required":["exposureCount","assessmentCount","confidence","masteryCandidate"],"description":"What ingesting this item applied to the learner-skill state. Items that were not accepted apply nothing. `masteryCandidate` is the 0–100 mastery an accepted assessment offered; the state keeps the higher of it and its prior value.","properties":{"exposureCount":{"type":"integer","minimum":0,"maximum":1},"assessmentCount":{"type":"integer","minimum":0,"maximum":1},"confidence":{"type":"number","minimum":0},"masteryCandidate":{"type":["number","null"],"minimum":0,"maximum":100}}},"occurredAt":{"type":"string","format":"date-time"},"recordedAt":{"type":"string","format":"date-time"},"contentRef":{"anyOf":[{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},{"type":"null"}]}}}},"page":{"type":"object","additionalProperties":false,"required":["limit","nextCursor"],"properties":{"limit":{"type":"integer","minimum":1,"maximum":100},"nextCursor":{"type":["string","null"],"description":"Pass as `cursor` for the next, older page. A page can hold fewer than `limit` items when some are filtered by client-system binding."}}}}}}},"CaleJwksResponse":{"type":"object","additionalProperties":false,"required":["keys"],"properties":{"keys":{"type":"array","minItems":1,"items":{"type":"object","additionalProperties":true,"required":["kty","crv","x","y","alg","use","kid"],"properties":{"kty":{"const":"EC"},"crv":{"const":"P-256"},"x":{"type":"string"},"y":{"type":"string"},"alg":{"const":"ES256"},"use":{"const":"sig"},"kid":{"type":"string"}}}}}},"CaleSkillReference":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","minLength":1},"alias":{"type":"string","minLength":1},"version":{"type":"string","minLength":1}},"anyOf":[{"required":["id"]},{"required":["alias"]}]},"CaleAlignmentWrite":{"type":"object","additionalProperties":false,"required":["resource","alignments"],"properties":{"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"alignments":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string","minLength":1},"skillVersion":{"type":"string","minLength":1},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}}}},"XapiStatementResult":{"type":"object","required":["statements","more"],"properties":{"statements":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"xAPI Statement"}},"more":{"type":"string","description":"Relative URL to the next page, empty string when no further pages exist"}}},"GraphEnvelope":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true},"meta":{"type":"object","additionalProperties":true}}},"CreatePublishV2Error":{"type":"object","required":["ok","error","code","error_id"],"properties":{"ok":{"type":"boolean","enum":[false]},"error":{"type":"string"},"code":{"type":"string"},"error_id":{"type":"string","format":"uuid"},"retryable":{"type":"boolean"}}}}},"security":[{"ApiKeyAuth":[]},{"BearerApiKey":[]}],"paths":{"/api/v1/cale/capabilities":{"get":{"tags":["CALE"],"operationId":"getCaleCapabilities","summary":"Discover Skills & Outcomes contract capabilities","responses":{"200":{"description":"Capabilities and limits","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data","principal"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["contractVersion","graph","limits","projectionValiditySeconds","permissions","receipt"],"properties":{"contractVersion":{"type":"string"},"graph":{"type":"object","additionalProperties":false,"required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"limits":{"type":"object","additionalProperties":false,"required":["resolverReferences","graphRoots","graphDepth","graphNodes","alignmentSets","subjects","skills","projectionCells"],"properties":{"resolverReferences":{"type":"integer"},"graphRoots":{"type":"integer"},"graphDepth":{"type":"integer"},"graphNodes":{"type":"integer"},"alignmentSets":{"type":"integer"},"subjects":{"type":"integer"},"skills":{"type":"integer"},"projectionCells":{"type":"integer"}}},"projectionValiditySeconds":{"type":"integer"},"permissions":{"type":"array","items":{"type":"string","enum":["cale:graph:read","cale:alignments:write","cale:learner-skills:read","cale:evidence:write","cale:mappings:review"]}},"receipt":{"type":"object","additionalProperties":false,"required":["algorithm","format","jwksPath"],"properties":{"algorithm":{"const":"ES256"},"format":{"const":"compact-jws"},"jwksPath":{"type":"string"}}}}},"principal":{"type":"object","additionalProperties":false,"required":["permissions","clientSystemIds"],"properties":{"permissions":{"type":"array","items":{"type":"string"}},"clientSystemIds":{"type":["array","null"],"items":{"type":"string"}}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Tenant not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/client-systems":{"get":{"tags":["CALE"],"operationId":"listCaleClientSystems","summary":"List registered client learning systems visible to the principal","responses":{"200":{"description":"Client systems","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","kind","name","status"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["lms","authoring_platform","assessment_platform","learning_application","other"]},"name":{"type":"string"},"status":{"type":"string","enum":["active","disabled"]},"reserved":{"type":"boolean"},"subjectIdentity":{"type":"string","enum":["runtime_learner_ref"],"description":"Present when this system's subjectRef is the learner ref it launches with, so learner-skill reads and evidence from the LMS service and `internal_product`/`admin` callers address the learner's runtime record. `public_api` keys keep client-scoped subjects."}}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["CALE"],"operationId":"registerCaleClientSystem","summary":"Register a tenant-scoped client learning system","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["id","kind","name"],"properties":{"id":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["lms","authoring_platform","assessment_platform","learning_application","other"]},"name":{"type":"string","minLength":1,"maxLength":200},"status":{"type":"string","enum":["active","disabled"]},"subjectIdentity":{"type":"string","enum":["runtime_learner_ref"],"nullable":true,"description":"Set when subjectRef is the learner ref this system launches with. Omit to keep the stored value; null clears it. Only the Allure LMS service or an `admin` key may send this field (403 `SUBJECT_IDENTITY_FORBIDDEN` otherwise), and every change is written to the audit log. It takes effect for the LMS service and `internal_product`/`admin` callers only: a `public_api` key bound to the system keeps its client-scoped subjects."}}}}}},"responses":{"201":{"description":"Client system registered","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","kind","name","status"],"properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["lms","authoring_platform","assessment_platform","learning_application","other"]},"name":{"type":"string"},"status":{"type":"string","enum":["active","disabled"]},"reserved":{"type":"boolean"},"subjectIdentity":{"type":"string","enum":["runtime_learner_ref"],"description":"Present when this system's subjectRef is the learner ref it launches with, so learner-skill reads and evidence from the LMS service and `internal_product`/`admin` callers address the learner's runtime record. `public_api` keys keep client-scoped subjects."}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Internal-product or admin principal required; `SUBJECT_IDENTITY_FORBIDDEN` when subjectIdentity is sent by anything but the LMS service or an admin key; `WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/frameworks":{"get":{"tags":["CALE"],"operationId":"listCaleFrameworks","summary":"List canonical skill frameworks","responses":{"200":{"description":"Framework list","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name","version","status","checksum","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"version":{"type":"string"},"status":{"type":"string","enum":["active","deprecated","retired"]},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"updatedAt":{"type":"string","format":"date-time"},"skills":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/frameworks/{frameworkId}":{"get":{"tags":["CALE"],"operationId":"getCaleFramework","summary":"Get a canonical framework","parameters":[{"name":"frameworkId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Framework","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","name","version","status","checksum","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"version":{"type":"string"},"status":{"type":"string","enum":["active","deprecated","retired"]},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"updatedAt":{"type":"string","format":"date-time"},"skills":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Framework not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/frameworks/{frameworkId}/skills":{"get":{"tags":["CALE"],"operationId":"listCaleFrameworkSkills","summary":"List public skills in a framework","parameters":[{"name":"frameworkId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill list","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Framework not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/skills/{skillId}":{"get":{"tags":["CALE"],"operationId":"getCaleSkill","summary":"Get a canonical skill","parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Skill not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/skills/resolve":{"post":{"tags":["CALE"],"operationId":"resolveCaleSkills","summary":"Resolve up to 100 skill references in request order","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["references"],"properties":{"references":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","minLength":1},"alias":{"type":"string","minLength":1},"version":{"type":"string","minLength":1}},"anyOf":[{"required":["id"]},{"required":["alias"]}]}}}}}}},"responses":{"200":{"description":"Per-reference resolution results","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["reference","status"],"properties":{"reference":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","minLength":1},"alias":{"type":"string","minLength":1},"version":{"type":"string","minLength":1}},"anyOf":[{"required":["id"]},{"required":["alias"]}]},"status":{"type":"string","enum":["resolved","unknown","proposed","cross_tenant","deprecated","retired","version_conflict"]},"skillId":{"type":"string"},"canonicalVersion":{"type":"string"},"skill":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/graph/query":{"post":{"tags":["CALE"],"operationId":"queryCaleGraph","summary":"Read a bounded deterministic graph projection","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["rootSkillIds"],"properties":{"rootSkillIds":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"string","minLength":1}},"depth":{"type":"integer","minimum":0,"maximum":2},"relationshipTypes":{"type":"array","items":{"type":"string","enum":["prerequisite","related"]}}}}}}},"responses":{"200":{"description":"Five-minute graph projection","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["revision","checksum","nodes","edges","truncated","observedAt","validUntil"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"nodes":{"type":"array","maxItems":200,"items":{"type":"object","additionalProperties":false,"required":["id","frameworkId","version","name","description","domain","parentId","lifecycleState","replacementSkillId","aliases","checksum"],"properties":{"id":{"type":"string"},"frameworkId":{"type":["string","null"]},"version":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"domain":{"type":"string"},"parentId":{"type":["string","null"]},"lifecycleState":{"type":"string","enum":["active","deprecated","retired"]},"replacementSkillId":{"type":["string","null"]},"aliases":{"type":"array","items":{"type":"string"}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}},"edges":{"type":"array","description":"Accepted links only. A `prerequisite` edge points from the prerequisite (`fromSkillId`) to the skill it unlocks (`toSkillId`). A `related` edge has no direction.","items":{"type":"object","additionalProperties":false,"required":["fromSkillId","toSkillId","type","weight"],"properties":{"fromSkillId":{"type":"string"},"toSkillId":{"type":"string"},"type":{"type":"string","enum":["prerequisite","related"]},"weight":{"type":["number","null"]}}}},"truncated":{"type":"boolean"},"observedAt":{"type":"string","format":"date-time"},"validUntil":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/alignments/validate":{"post":{"tags":["CALE"],"operationId":"validateCaleAlignment","summary":"Preflight an alignment set without persisting it","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["resource","alignments"],"properties":{"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"alignments":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string","minLength":1},"skillVersion":{"type":"string","minLength":1},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}}}}}}},"responses":{"200":{"description":"Valid canonical set","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","required":["ok","errors"],"properties":{"ok":{"type":"boolean"},"code":{"type":"string"},"errors":{"type":"array","items":{"type":"object","additionalProperties":true}},"canonical":{"type":"object","required":["resource","alignments"],"properties":{"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}}}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graph":{"type":"object","additionalProperties":false,"required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"policyRevision":{"type":"string"}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Permission or client-system scope denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"Alignment policy rejection","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","required":["ok","errors"],"properties":{"ok":{"type":"boolean"},"code":{"type":"string"},"errors":{"type":"array","items":{"type":"object","additionalProperties":true}},"canonical":{"type":"object","required":["resource","alignments"],"properties":{"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}}}},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graph":{"type":"object","additionalProperties":false,"required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"policyRevision":{"type":"string"}}}}}}}}}}},"/api/v1/cale/alignments/{alignmentId}":{"put":{"tags":["CALE"],"operationId":"putCaleAlignment","summary":"Persist the canonical accepted set for one immutable resource version","parameters":[{"name":"alignmentId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":128}},{"name":"If-Match","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["resource","alignments"],"properties":{"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"alignments":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string","minLength":1},"skillVersion":{"type":"string","minLength":1},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}}}}}}},"responses":{"200":{"description":"Updated or replayed alignment","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","resource","revision","checksum","graphRevision","graphChecksum","policyRevision","alignments","receipt","updatedAt"],"properties":{"id":{"type":"string"},"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graphRevision":{"type":"integer","minimum":1},"graphChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"policyRevision":{"type":"string"},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}},"receipt":{"type":"string","description":"ES256 compact JWS receipt."},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"201":{"description":"Created alignment","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["id","resource","revision","checksum","graphRevision","graphChecksum","policyRevision","alignments","receipt","updatedAt"],"properties":{"id":{"type":"string"},"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graphRevision":{"type":"integer","minimum":1},"graphChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"policyRevision":{"type":"string"},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}},"receipt":{"type":"string","description":"ES256 compact JWS receipt."},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Permission or client-system scope denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Idempotency or revision conflict","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"Alignment policy rejection","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"428":{"description":"Required concurrency headers missing","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Receipt signing or idempotency replay unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/alignments":{"get":{"tags":["CALE"],"operationId":"listCaleAlignments","summary":"Read canonical alignment sets by client resource","parameters":[{"name":"clientSystemId","in":"query","required":true,"schema":{"type":"string"}},{"name":"resourceType","in":"query","schema":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]}},{"name":"resourceId","in":"query","schema":{"type":"string"}},{"name":"resourceVersion","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Alignment sets","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","resource","revision","checksum","graphRevision","graphChecksum","policyRevision","alignments","receipt","updatedAt"],"properties":{"id":{"type":"string"},"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"graphRevision":{"type":"integer","minimum":1},"graphChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"policyRevision":{"type":"string"},"alignments":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["skillId","skillVersion","relation"],"properties":{"skillId":{"type":"string"},"skillVersion":{"type":"string"},"relation":{"type":"string","enum":["teaches","assesses","requires"]},"weight":{"type":"number","minimum":0,"maximum":1}}}},"receipt":{"type":"string","description":"ES256 compact JWS receipt."},"updatedAt":{"type":"string","format":"date-time"}}}}}}}}},"400":{"description":"Missing client system","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Permission or client-system scope denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/evidence/batch":{"post":{"tags":["CALE"],"operationId":"ingestCaleEvidenceBatch","summary":"Ingest a batch of native or human evidence items","description":"Accepts idempotent evidence items from a client learning system. Each item is independently accepted, duplicated, rejected, or quarantined. Accepted items contribute to learner-skill projections. Signed alignment receipts remain on PUT /api/v1/cale/alignments/{alignmentId}; validate stays preflight. Authenticate with a partner API key (Bearer or X-API-Key) or, for AllureLMS, `X-AllureLMS-Service-Token` plus `X-AllureConnect-Tenant-Id`. Requires `cale:evidence:write` on the API key when using partner auth.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["clientSystemId","items"],"properties":{"clientSystemId":{"type":"string","minLength":1,"maxLength":200},"items":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["evidenceId","subject","skillId","kind","occurredAt"],"properties":{"evidenceId":{"type":"string","minLength":1,"maxLength":200},"subject":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"skillId":{"type":"string","minLength":1},"skillVersion":{"type":"string","minLength":1},"kind":{"type":"string","enum":["exposure","assessment","completion","human_approval"]},"occurredAt":{"type":"string","format":"date-time"},"scoreScaled":{"type":"number","minimum":0,"maximum":1},"assessedLevel":{"type":"string","enum":["novice","working","proficient","expert"],"description":"The highest level this assessment is built to prove. The score counts toward the top of that level (24, 49, 74, 100) and no further. Omit to read the score on the whole 0–100 scale. Accepted only when `kind` is `assessment` or `human_approval`; on `exposure` or `completion` it is a validation error."},"demandRatings":{"type":"object","propertyNames":{"pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"maxProperties":8,"description":"What the item demanded, as its rating on one or more demand ladders: ladder id → step id, for example `{ \"thinking\": \"apply\" }`. Built-in ladders: `thinking`, `relating`, `doing`. With no `assessedLevel`, these, `demonstrationMode` and the kind of skill decide the highest level the score can prove. Each ladder id and each step id is lower case, starts with a letter and is at most 40 characters (letters, digits and `_`); an id that is not refuses the whole request as a validation error (400), before any item is read. A well-formed rating that names no built-in ladder or step quarantines the item (`INVALID_DEMAND_RATING`) and the rest of the batch goes on. Accepted only when `kind` is `assessment` or `human_approval`; on `exposure` or `completion` it is a validation error."},"demonstrationMode":{"type":"string","enum":["knowledge_check","applied_exercise","simulated_performance","observed_performance","sustained_performance"],"description":"How real the demonstration was. Omit both this and `demandRatings` and nothing changes. Accepted only when `kind` is `assessment` or `human_approval`; on `exposure` or `completion` it is a validation error."},"passMarkScaled":{"type":"number","minimum":0,"maximum":1,"description":"The assessment’s own pass mark as a scaled score. The score is then read against it instead of on the raw scale: reaching it lands on the lower bound of the level the item can prove (with nothing else set, the start of Proficient), full marks on the top, with a straight line between; below it, a straight line from 0 up to that lower bound. Omit it, or send 0, and the score is read as before. Accepted only when `kind` is `assessment` or `human_approval`; on `exposure` or `completion` it is a validation error."},"weight":{"type":"number","minimum":0,"maximum":1},"resource":{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},"metadata":{"type":"object","additionalProperties":true}}}}}}}}},"responses":{"200":{"description":"Per-item dispositions","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["results"],"properties":{"results":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["evidenceId","disposition"],"properties":{"evidenceId":{"type":"string"},"disposition":{"type":"string","enum":["accepted","duplicate","rejected","quarantined"]},"reasonCode":{"type":"string"}}}}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Permission or client-system scope denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Tenant or client system not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"`RUNTIME_IDENTITY_UNAVAILABLE`: the server could not resolve its own origin, so a launch ref on a client system with `subjectIdentity` cannot be resolved. Retry later; nothing was read or written.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/learner-skills/query":{"post":{"tags":["CALE"],"operationId":"queryCaleLearnerSkills","summary":"Query private verified-outcome projections","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["subjects","skillIds"],"properties":{"subjects":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}}},"skillIds":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","minLength":1}}}}}}},"responses":{"200":{"description":"At most 5,000 projection cells; Cache-Control private, no-store","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["projections"],"properties":{"projections":{"type":"array","maxItems":5000,"items":{"type":"object","required":["subject","skillId"],"properties":{"subject":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"skillId":{"type":"string"},"skillVersion":{"type":"string"},"state":{"type":"string","enum":["unobserved","developing","verified","expired","revoked"]},"reasonCodes":{"type":"array","items":{"type":"string"}},"mastery":{"type":"number"},"confidence":{"type":"number"},"evidence":{"type":"object","additionalProperties":false,"required":["acceptedCount","assessmentCount","exposureCount","applied","quality"],"properties":{"acceptedCount":{"type":"integer","minimum":0},"assessmentCount":{"type":"integer","minimum":0},"exposureCount":{"type":"integer","minimum":0},"applied":{"type":"boolean"},"quality":{"type":"string","enum":["none","exposure_only","qualifying"]}}},"explanation":{"type":"object","description":"A line to show beside the level describing how many scored results stand behind it. This release stores no strongest demonstration fact.","required":["scoredResults","strongestEvidence","text"],"properties":{"scoredResults":{"type":"integer","minimum":0},"strongestEvidence":{"type":"null","description":"This release stores no strongest demonstration fact."},"text":{"type":"string","description":"For example: \"Based on 3 scored results.\""}}},"decayState":{"type":"string","enum":["current","decaying","lapsed"]},"lastDemonstratedAt":{"type":["string","null"],"format":"date-time"},"policyRevision":{"type":"string"},"sourceRevision":{"type":"integer","minimum":1},"sourceChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"observedAt":{"type":"string","format":"date-time"},"validUntil":{"type":"string","format":"date-time"},"error":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","enum":["CLIENT_SYSTEM_NOT_FOUND","SKILL_NOT_FOUND"]}}}},"oneOf":[{"required":["error"]},{"required":["skillVersion","state","reasonCodes","mastery","confidence","evidence","decayState","lastDemonstratedAt","policyRevision","sourceRevision","sourceChecksum","observedAt","validUntil"]}]}}}}}}}}},"400":{"description":"Validation or projection-cell limit error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Permission or client-system scope denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"`RUNTIME_IDENTITY_UNAVAILABLE`: the server could not resolve its own origin, so a launch ref on a client system with `subjectIdentity` cannot be resolved. Retry later; nothing was read or written.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/subjects/{clientSystemId}/{subjectRef}/skills/{skillId}":{"get":{"tags":["CALE"],"operationId":"getCaleSubjectSkill","summary":"Get one private subject-skill projection","parameters":[{"name":"clientSystemId","in":"path","required":true,"schema":{"type":"string"}},{"name":"subjectRef","in":"path","required":true,"schema":{"type":"string"}},{"name":"skillId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Projection; Cache-Control private, no-store","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","required":["subject","skillId"],"properties":{"subject":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"skillId":{"type":"string"},"skillVersion":{"type":"string"},"state":{"type":"string","enum":["unobserved","developing","verified","expired","revoked"]},"reasonCodes":{"type":"array","items":{"type":"string"}},"mastery":{"type":"number"},"confidence":{"type":"number"},"evidence":{"type":"object","additionalProperties":false,"required":["acceptedCount","assessmentCount","exposureCount","applied","quality"],"properties":{"acceptedCount":{"type":"integer","minimum":0},"assessmentCount":{"type":"integer","minimum":0},"exposureCount":{"type":"integer","minimum":0},"applied":{"type":"boolean"},"quality":{"type":"string","enum":["none","exposure_only","qualifying"]}}},"explanation":{"type":"object","description":"A line to show beside the level describing how many scored results stand behind it. This release stores no strongest demonstration fact.","required":["scoredResults","strongestEvidence","text"],"properties":{"scoredResults":{"type":"integer","minimum":0},"strongestEvidence":{"type":"null","description":"This release stores no strongest demonstration fact."},"text":{"type":"string","description":"For example: \"Based on 3 scored results.\""}}},"decayState":{"type":"string","enum":["current","decaying","lapsed"]},"lastDemonstratedAt":{"type":["string","null"],"format":"date-time"},"policyRevision":{"type":"string"},"sourceRevision":{"type":"integer","minimum":1},"sourceChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"},"observedAt":{"type":"string","format":"date-time"},"validUntil":{"type":"string","format":"date-time"},"error":{"type":"object","additionalProperties":false,"required":["code"],"properties":{"code":{"type":"string","enum":["CLIENT_SYSTEM_NOT_FOUND","SKILL_NOT_FOUND"]}}}},"oneOf":[{"required":["error"]},{"required":["skillVersion","state","reasonCodes","mastery","confidence","evidence","decayState","lastDemonstratedAt","policyRevision","sourceRevision","sourceChecksum","observedAt","validUntil"]}]}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Permission or client-system scope denied; `WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Projection not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"`RUNTIME_IDENTITY_UNAVAILABLE`: the server could not resolve its own origin, so a launch ref on a client system with `subjectIdentity` cannot be resolved. Retry later; nothing was read or written.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/subjects/{clientSystemId}/{subjectRef}/skills/{skillId}/evidence":{"get":{"tags":["CALE"],"operationId":"listCaleSubjectSkillEvidence","summary":"List the evidence behind one subject-skill state","description":"Evidence items for one learner and skill, newest first: source, outcome, applied delta, timestamps and content reference. Free-form item metadata is not returned. Requires `cale:learner-skills:read` and a key binding to `clientSystemId`; public keys only see items submitted by client systems they are bound to. Tenant scope comes from the key. `graphRead` tier. Rate limited per key. Cache-Control private, no-store.","parameters":[{"name":"clientSystemId","in":"path","required":true,"schema":{"type":"string"}},{"name":"subjectRef","in":"path","required":true,"schema":{"type":"string"}},{"name":"skillId","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque `nextCursor` from the previous page."}],"responses":{"200":{"description":"Evidence page","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"object","additionalProperties":false,"required":["subject","skillId","items","page"],"properties":{"subject":{"type":"object","additionalProperties":false,"required":["clientSystemId","subjectRef"],"properties":{"clientSystemId":{"type":"string","minLength":1},"subjectRef":{"type":"string","minLength":1,"maxLength":512}}},"skillId":{"type":"string"},"items":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["evidenceId","source","outcome","delta","occurredAt","recordedAt","contentRef"],"properties":{"evidenceId":{"type":"string"},"source":{"type":"object","additionalProperties":false,"required":["clientSystemId","kind"],"properties":{"clientSystemId":{"type":"string"},"kind":{"type":"string","enum":["exposure","assessment","completion","human_approval"]}}},"outcome":{"type":"object","additionalProperties":false,"required":["disposition","reasonCode","scoreScaled","weight"],"properties":{"disposition":{"type":"string","enum":["accepted","duplicate","rejected","quarantined"]},"reasonCode":{"type":["string","null"]},"scoreScaled":{"type":["number","null"],"minimum":0,"maximum":1},"weight":{"type":["number","null"],"minimum":0,"maximum":1}}},"delta":{"type":"object","additionalProperties":false,"required":["exposureCount","assessmentCount","confidence","masteryCandidate"],"description":"What ingesting this item applied to the learner-skill state. Items that were not accepted apply nothing. `masteryCandidate` is the 0–100 mastery an accepted assessment offered; the state keeps the higher of it and its prior value.","properties":{"exposureCount":{"type":"integer","minimum":0,"maximum":1},"assessmentCount":{"type":"integer","minimum":0,"maximum":1},"confidence":{"type":"number","minimum":0},"masteryCandidate":{"type":["number","null"],"minimum":0,"maximum":100}}},"occurredAt":{"type":"string","format":"date-time"},"recordedAt":{"type":"string","format":"date-time"},"contentRef":{"anyOf":[{"type":"object","additionalProperties":false,"required":["clientSystemId","resourceType","resourceId","resourceVersion","draftChecksum"],"properties":{"clientSystemId":{"type":"string","minLength":1},"resourceType":{"type":"string","enum":["course_version","module","activity","native_assessment","demonstration","external_package_activity"]},"resourceId":{"type":"string","minLength":1},"resourceVersion":{"type":"string","minLength":1},"draftChecksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}},{"type":"null"}]}}}},"page":{"type":"object","additionalProperties":false,"required":["limit","nextCursor"],"properties":{"limit":{"type":"integer","minimum":1,"maximum":100},"nextCursor":{"type":["string","null"],"description":"Pass as `cursor` for the next, older page. A page can hold fewer than `limit` items when some are filtered by client-system binding."}}}}}}}}}},"400":{"description":"Invalid limit or cursor","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"A valid Connect API key or internal-product principal is required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Permission or client-system scope denied; `WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Client system not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"`RUNTIME_IDENTITY_UNAVAILABLE`: the server could not resolve its own origin, so a launch ref on a client system with `subjectIdentity` cannot be resolved. Retry later; nothing was read or written.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/cale/.well-known/jwks.json":{"get":{"tags":["CALE"],"operationId":"getCaleJwks","summary":"Get public ES256 receipt-verification keys","security":[],"responses":{"200":{"description":"JSON Web Key Set","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["keys"],"properties":{"keys":{"type":"array","minItems":1,"items":{"type":"object","additionalProperties":true,"required":["kty","crv","x","y","alg","use","kid"],"properties":{"kty":{"const":"EC"},"crv":{"const":"P-256"},"x":{"type":"string"},"y":{"type":"string"},"alg":{"const":"ES256"},"use":{"const":"sig"},"kid":{"type":"string"}}}}}}}}},"503":{"description":"Signing key unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/health":{"get":{"tags":["Health"],"summary":"Service health status","description":"Check the health status of the Allure Connect service. This endpoint is publicly accessible and does not require authentication.","operationId":"getHealthStatus","security":[],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","unhealthy"]},"service":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"checks":{"type":"object","properties":{"database":{"type":"boolean"}}},"error":{"type":"string","nullable":true}}},"examples":{"healthy":{"value":{"status":"healthy","service":"scorm-api","version":"1.0.0","timestamp":"2025-01-15T10:30:00.000Z","checks":{"database":true},"error":null}},"degraded":{"value":{"status":"degraded","service":"scorm-api","version":"1.0.0","timestamp":"2025-01-15T10:30:00.000Z","checks":{"database":true},"error":"Storage backend experiencing high latency"}}}}}},"503":{"description":"Service is degraded or unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","unhealthy"]},"service":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"checks":{"type":"object","properties":{"database":{"type":"boolean"}}},"error":{"type":"string","nullable":true}}},"examples":{"unhealthy":{"value":{"status":"unhealthy","service":"scorm-api","version":"1.0.0","timestamp":"2025-01-15T10:30:00.000Z","checks":{"database":false},"error":"Database connection failed"}}}}}}}}},"/api/v1/keys/me":{"get":{"tags":["Credentials"],"summary":"Validate the current API key","description":"Authenticate the supplied API key and return non-secret metadata about the resolved tenant, scope, and key mode. This endpoint never returns the API key, key suffix, or hashed secret.","operationId":"getCurrentApiKey","responses":{"200":{"description":"Authenticated API key metadata","headers":{"Cache-Control":{"schema":{"type":"string"},"description":"Always private, no-store, max-age=0"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","key"],"properties":{"ok":{"type":"boolean","enum":[true]},"key":{"type":"object","required":["id","tenant_id","scope","mode","is_sandbox","label","source","permissions"],"properties":{"id":{"type":"string","description":"Non-secret API key id"},"tenant_id":{"type":"string","description":"External tenant id resolved from the key"},"scope":{"type":"string","enum":["public_api","internal_product","admin"]},"mode":{"type":"string","enum":["test","live"]},"is_sandbox":{"type":"boolean"},"label":{"type":"string","description":"Human-readable key label"},"source":{"type":"string","enum":["convex","env","clerk_session"]},"permissions":{"type":"array","items":{"type":"string","enum":["cale:graph:read","cale:alignments:write","cale:learner-skills:read","cale:evidence:write","cale:mappings:review"]}},"client_system_ids":{"type":"array","items":{"type":"string"}}}}}},"examples":{"liveKey":{"value":{"ok":true,"key":{"id":"key_abc123","tenant_id":"tenant_acme","scope":"public_api","mode":"live","is_sandbox":false,"label":"Production integration","source":"convex","permissions":["cale:graph:read"],"client_system_ids":["acme-lms"]}}}}}}},"401":{"description":"Authentication required or API key invalid","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages":{"get":{"tags":["Packages"],"summary":"List SCORM packages for a tenant","description":"Retrieve a paginated list of SCORM packages for the authenticated tenant.\n\n**Features:**\n- Returns all packages accessible by the API key tenant\n- Packages are sorted by creation date (newest first)\n- Includes package metadata, versions, and launch URLs\n- Pagination via `limit`/`offset` (default: 50 per page, max: 500)\n- `pagination.totalIsLowerBound` is true only when the bounded read ceiling is reached\n\n**Example:**\n```bash\ncurl -H \"X-API-Key: your-api-key\" \\\n  https://app.allureconnect.com/api/v1/packages\n```","operationId":"listPackages","parameters":[{"name":"tenant_id","in":"query","required":false,"deprecated":true,"schema":{"type":"string"},"description":"Ignored compatibility parameter. The API key always determines the tenant."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":50},"description":"Maximum results to return (default: 50, max: 500)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0},"description":"Number of results to skip before returning the page"}],"responses":{"200":{"description":"List of packages for the tenant","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Rate limit (requests per minute)"},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in current window"},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when rate limit resets"}},"content":{"application/json":{"schema":{"type":"object","required":["packages"],"properties":{"packages":{"type":"array","items":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean"},"totalIsLowerBound":{"type":"boolean","description":"True when total is a bounded lower estimate rather than an exact count."}}}}},"examples":{"success":{"value":{"packages":[{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}],"pagination":{"total":1,"limit":50,"offset":0,"hasMore":false,"totalIsLowerBound":false}}}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Transient backend failure. Retry after the delay in Retry-After.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0},"description":"Seconds to wait before retrying the request","example":5}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"examples":{"backendUnavailable":{"value":{"error":"The learning record backend is temporarily unavailable. Retry the request.","code":"BACKEND_UNAVAILABLE","retryable":true}}}}}}}}},"/api/v1/packages/{packageId}":{"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"},"description":"SCORM package identifier"}],"get":{"tags":["Packages"],"summary":"Retrieve package details","description":"Get detailed information about a specific SCORM package, including metadata, versions, and launch URLs.\n\n**Package Information:**\n- Package ID, tenant, slug, title, content type, and lifecycle status\n- Current version, rolling launch activity, and storage usage\n- Organization and acquisition-source metadata when present\n- Version records with manifest, launch, and downloadable-artifact locations when present\n\n**Example:**\n```bash\ncurl -H \"X-API-Key: your-api-key\" \\\n  https://app.allureconnect.com/api/v1/packages/{packageId}\n```","operationId":"getPackage","responses":{"200":{"description":"Package details","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Rate limit (requests per minute)"},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in current window"},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when rate limit resets"}},"content":{"application/json":{"schema":{"type":"object","required":["package","versions"],"properties":{"package":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}},"versions":{"type":"array","items":{"type":"object","required":["id","packageId","versionLabel","contentType","status","manifestVersion","uploadedAt","storageKey"],"properties":{"id":{"type":"string"},"packageId":{"type":"string"},"versionLabel":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["uploaded","processing","ready","failed"]},"manifestVersion":{"type":"string","nullable":true},"uploadedAt":{"type":"string","format":"date-time"},"storageKey":{"type":"string"},"manifestUrl":{"type":"string","nullable":true},"launchUrl":{"type":"string","nullable":true},"artifactUrl":{"type":"string","nullable":true},"artifactFilename":{"type":"string","nullable":true},"artifactMimeType":{"type":"string","nullable":true},"platformTarget":{"type":"string","nullable":true}}}}}},"examples":{"success":{"value":{"package":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"},"versions":[{"id":"ver_1","packageId":"pkg_abc123","versionLabel":"1.2","contentType":"scorm","status":"ready","manifestVersion":"SCORM 1.2","uploadedAt":"2026-09-01T12:00:00.000Z","storageKey":"packages/tenant_example-workspace/pkg_abc123/1.2/course.zip"}]}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["Packages"],"summary":"Archive a package","description":"Archive a SCORM package. This is a reversible lifecycle action that retains versions, learner history, and stored content.\n\n**Requirements:**\n- Requires a package-capable tenant API key\n- Package must belong to the API key tenant\n- New launches stop while the package is archived\n- Use the signed-in Courses dashboard to restore or permanently delete archived content\n\n**Example:**\n```bash\ncurl -X DELETE https://app.allureconnect.com/api/v1/packages/{packageId} \\\n  -H \"X-API-Key: your-api-key\"\n```","operationId":"deletePackage","responses":{"200":{"description":"Package archived","content":{"application/json":{"schema":{"type":"object","required":["success","package_id","status"],"properties":{"success":{"type":"boolean","enum":[true]},"package_id":{"type":"string"},"status":{"type":"string","enum":["archived"]}}}}},"headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Rate limit (requests per minute)"},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in current window"},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when rate limit resets"}}},"403":{"description":"Tenant mismatch or insufficient package scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Package lifecycle is managed by Allure Create","content":{"application/json":{"schema":{"type":"object","required":["ok","error","code"],"properties":{"ok":{"type":"boolean","enum":[false]},"error":{"type":"string"},"code":{"type":"string","enum":["CREATE_PACKAGE_LIFECYCLE_MANAGED_BY_CREATE"]}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/{packageId}/launch":{"get":{"tags":["Packages","Sessions"],"summary":"Preview package launch metadata","description":"Returns a launch preview for the package (content type, public launch URL template, token TTL, supported origins) without creating a session. New launches are blocked when the package is archived or otherwise unavailable.","operationId":"previewPackageLaunch","parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"},"description":"Package identifier"}],"responses":{"200":{"description":"Launch preview","content":{"application/json":{"schema":{"type":"object","required":["launch"],"properties":{"launch":{"type":"object","properties":{"packageId":{"type":"string"},"contentType":{"type":"string"},"launchUrl":{"type":"string"},"tokenTtlSeconds":{"type":"integer"},"supportedOrigins":{"type":"array","items":{"type":"string","enum":["connect","lms","client"]}}}}}}}}},"403":{"description":"Create delivery not authorized for generic launch path","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Package lifecycle conflict: archived, processing, deletion pending, or deleted","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["PACKAGE_ARCHIVED","PACKAGE_NOT_READY","PACKAGE_DELETION_PENDING","PACKAGE_DELETED"]}}}}}}}},"post":{"tags":["Packages","Sessions"],"summary":"Create or resume a SCORM session and return launch info","description":"Create a new SCORM session or resume an existing session for a learner. Returns launch URL, session ID, and API endpoint for CMI data communication.\n\n**Session Creation:**\n- Creates a new session if `session_id` is not provided\n- Initializes CMI data for the learner\n- Returns launch URL for embedding in iframe or new window\n\n**Session Resume:**\n- Resumes an existing session if `session_id` is provided\n- Restores previous CMI data and progress\n- Allows learners to continue where they left off\n- Reusing a `session_id` from a different package or workspace returns `409 SESSION_ID_SCOPE_MISMATCH` — omit `session_id` to start a new session\n\n**Player Options:**\n- `show_chrome`: Show player controls (default: false)\n- `auto_complete_on_exit`: Auto-complete session on exit (default: false)\n- `open_in_new_window`: Open in new window instead of iframe (default: false)\n\n**Example:**\n```bash\ncurl -X POST https://app.allureconnect.com/api/v1/packages/{packageId}/launch \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_id\": \"learner-123\",\n    \"player_options\": {\n      \"show_chrome\": false,\n      \"auto_complete_on_exit\": false\n    }\n  }'\n```","operationId":"launchPackage","parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"SCORM package identifier","example":"5c9476b4-2c7a-4c38-8d44-6f6f64d1bf12"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user_id"],"properties":{"user_id":{"type":"string","description":"Identifier of the learner launching the package"},"session_id":{"type":"string","format":"uuid","nullable":true,"description":"Existing session to resume (optional)"},"learner_activity":{"type":"string","enum":["foreground_v1"],"description":"Explicit hosted learner foreground capture, requiring exclusive SCORM. Omit for author preview. Captures trusted visible input only, with signed immutable session.foreground_activity events; never infer activity from CMI or polling."},"runtime_protocol":{"type":"string","enum":["exclusive_v1"],"description":"Opt in to exclusive runtime ownership. Omission preserves legacy hosted/partner writes for new sessions and never downgrades an opted-in session. Scoped session reuse may upgrade this policy without resetting progress; new attempts retain it."},"new_attempt":{"type":"boolean","description":"Retake: start a fresh attempt on the existing `session_id` (fresh status, score, suspend data and time). Earlier attempts stay in `attempt_history` and reports. A repeated call while the new attempt is untouched reuses it. Without it, relaunching a completed session follows the course setting `completedRelaunchBehavior`: `resume` for courses created before the setting existed, `review` for new courses."},"player_options":{"type":"object","properties":{"show_chrome":{"type":"boolean"},"auto_complete_on_exit":{"type":"boolean"},"open_in_new_window":{"type":"boolean"}},"additionalProperties":false}}},"examples":{"newSession":{"value":{"user_id":"learner-123","player_options":{"show_chrome":false,"auto_complete_on_exit":false,"open_in_new_window":false}}},"resumeSession":{"value":{"user_id":"learner-123","session_id":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"responses":{"200":{"description":"Launch payload returned","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Rate limit (requests per minute)"},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in current window"},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when rate limit resets"}},"content":{"application/json":{"schema":{"type":"object","required":["package_id","session_id","launch_url","learner_id","content_type","storage_backend","expires_in_seconds"],"properties":{"package_id":{"type":"string","description":"Package identifier (e.g. pkg_…)"},"session_id":{"type":"string","format":"uuid"},"launch_url":{"type":"string","format":"uri","description":"Hosted player URL with signed session token in `?token=`. Embed as-is; do not strip query parameters."},"learner_id":{"type":"string","description":"Learner identifier from the launch request (`user_id`)."},"content_type":{"type":"string","enum":["scorm","vr_apk"]},"storage_backend":{"type":"string","enum":["r2","disabled"]},"expires_in_seconds":{"type":"integer","description":"Effective session token TTL after platform min/max clamping."},"attempt_number":{"type":"integer","minimum":1,"description":"Current attempt number for this session."}}},"examples":{"success":{"value":{"package_id":"pkg_example_scorm_course","session_id":"550e8400-e29b-41d4-a716-446655440000","learner_id":"learner-123","content_type":"scorm","storage_backend":"r2","launch_url":"https://app.allureconnect.com/player/550e8400-e29b-41d4-a716-446655440000?token=REDACTED_LAUNCH_TOKEN","expires_in_seconds":14400}}}}}},"402":{"description":"ACTIVE_LEARNER_CAP_REACHED: the workspace reached its Free active-learner cap (or its TEST-mode allowance of 25 active test learners)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package or session not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"examples":{"packageNotFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"5c9476b4-2c7a-4c38-8d44-6f6f64d1bf12"}}},"sessionNotFound":{"value":{"error":"Session not found","code":"NOT_FOUND","details":{"resource":"session","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}},"409":{"description":"Launch conflict: package lifecycle, or session_id already belongs to a different package or workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["PACKAGE_ARCHIVED","PACKAGE_NOT_READY","PACKAGE_DELETION_PENDING","PACKAGE_DELETED","SESSION_ID_SCOPE_MISMATCH"]}}},"examples":{"sessionScopeMismatch":{"value":{"error":"The provided session_id already belongs to a different package or workspace. Omit session_id to start a new session, or resume the original package.","code":"SESSION_ID_SCOPE_MISMATCH"}}}}}},"410":{"description":"FREE_PLAN_PACKAGE_EXPIRED: Free-plan uploads expire 30 days after upload; upgrading restores them","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/sessions":{"get":{"tags":["Sessions"],"summary":"List sessions with filtering and pagination","description":"List SCORM sessions for the authenticated tenant. The tenant is resolved from the API key, so no tenant parameter is required.\n\n**Features:**\n- Filter by user or package\n- Pagination via `limit`/`offset` (default: 20 per page, max: 100)\n- `page` is a legacy alias translated to `offset` using the current `limit`\n- `pagination.total_is_lower_bound` is true only if the backend safety ceiling is reached\n\n**Example:**\n```bash\ncurl -H \"X-API-Key: your-api-key\" \\\n  \"https://app.allureconnect.com/api/v1/sessions?package_id=550e8400-e29b-41d4-a716-446655440000&limit=20&offset=0\"\n```","operationId":"listSessions","parameters":[{"name":"user_id","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by user ID"},{"name":"package_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Filter by package ID"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Maximum results to return (default: 20, max: 100)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0},"description":"Number of results to skip before returning the page"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Legacy alias — translated to offset using the current limit. Prefer limit/offset."}],"responses":{"200":{"description":"Paginated session list","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Rate limit (requests per minute)"},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in current window"},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when rate limit resets"}},"content":{"application/json":{"schema":{"type":"object","properties":{"sessions":{"type":"array","items":{"allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"attempts":{"type":"integer","nullable":true,"description":"Current attempt number (alias of `attempt_number`)."},"attempt_number":{"type":"integer","minimum":1,"description":"Current attempt number; status, score and time describe this attempt."},"launch_mode":{"type":"string","enum":["normal","review"],"description":"`review` when the hosted player opens a completed attempt read-only (cmi.mode=review)."},"start_over_allowed":{"type":"boolean","description":"Whether the hosted player offers \"Start over\" for the current attempt."},"attempt_history":{"type":"array","description":"Session detail only: up to 20 attempts, newest first. Earlier attempts keep their results after a retake or reset.","items":{"type":"object","properties":{"attempt_number":{"type":"integer"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","additionalProperties":true},"time_spent_seconds":{"type":"number"},"progress_percent":{"type":"number"},"started_at":{"type":"string","format":"date-time"},"last_activity_at":{"type":"string","format":"date-time"},"superseded_at":{"type":"string","format":"date-time","nullable":true},"superseded_reason":{"type":"string","nullable":true,"enum":["learner_start_over","launch_new_attempt","relaunch_policy","dashboard_reset","api_reset",null]}}}},"cmi_data":{"type":"object","additionalProperties":true},"suspend_data":{"type":"string","nullable":true},"version":{"type":"integer","minimum":1,"description":"Optimistic-locking revision. Increments on each committed update; pass the latest value back as `version` in PUT to detect concurrent writes."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","nullable":true}}},{"type":"object","properties":{"package":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}}}}]}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_more":{"type":"boolean"},"hasMore":{"type":"boolean"},"total_is_lower_bound":{"type":"boolean","description":"True only when the safety read ceiling was reached and total is a lower bound."},"totalIsLowerBound":{"type":"boolean"},"page":{"type":"integer","deprecated":true,"description":"Compatibility alias derived from offset and limit."},"total_pages":{"type":"integer","deprecated":true,"description":"Compatibility alias. This is also a lower bound when total_is_lower_bound is true."},"has_next":{"type":"boolean","deprecated":true,"description":"Compatibility alias for has_more."},"has_prev":{"type":"boolean","deprecated":true,"description":"Compatibility alias indicating offset is greater than zero."}}}}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Transient backend failure. Retry after the delay in Retry-After.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0},"description":"Seconds to wait before retrying the request","example":5}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"examples":{"backendUnavailable":{"value":{"error":"The learning record backend is temporarily unavailable. Retry the request.","code":"BACKEND_UNAVAILABLE","retryable":true}}}}}}}}},"/api/v1/sessions/{sessionId}/activity":{"post":{"tags":["Sessions"],"operationId":"recordSessionForegroundActivity","summary":"Capture opted-in hosted learner input","description":"Hosted producer only. Session launch Bearer token required; API keys are not a substitute. Requires learner_activity=foreground_v1 and current exclusive recording owner/attempt. No client timestamps, user or tenant fields. Sequence increases per owner; duplicate/out-of-order sequences are inert and accepted captures are limited to one per minute. The server captures time before durable signed delivery. Never call from timers, polling, CMI commits, author preview, or offline replay.","security":[{"LaunchToken":[]}],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["runtime_id","attempt","sequence"],"properties":{"runtime_id":{"type":"string","format":"uuid"},"attempt":{"type":"integer","minimum":1},"sequence":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"Accepted or duplicate/throttled (recorded false)"},"400":{"description":"Invalid body"},"401":{"description":"Missing/invalid launch token"},"404":{"description":"Session tenant mismatch"},"409":{"description":"Activity not enabled, stale runtime or attempt"},"503":{"description":"Transient backend failure. Retry after the delay in Retry-After.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0},"description":"Seconds to wait before retrying the request","example":5}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"examples":{"backendUnavailable":{"value":{"error":"The learning record backend is temporarily unavailable. Retry the request.","code":"BACKEND_UNAVAILABLE","retryable":true}}}}}}}}},"/api/v1/sessions/{sessionId}":{"post":{"tags":["Sessions"],"operationId":"claimSessionRuntime","summary":"Claim a browser runtime before starting content","description":"Requires a session explicitly launched with runtime_protocol=exclusive_v1; legacy sessions return 409 RUNTIME_PROTOCOL_NOT_ENABLED. Authenticated API key or session launch token. Atomically compare expected_runtime_id and attempt, then return the current session snapshot and server-derived runtimeMode. Same-owner retries are idempotent. Review launches cannot write or displace an active recording owner. A recording owner may save final answers after completion. Never-claimed legacy writers retain existing behavior; reset creates an unowned attempt. Deploy the compatible backend before claim-aware players.","security":[{"ApiKeyAuth":[]},{"LaunchToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["runtime_id","expected_runtime_id","attempt"],"properties":{"runtime_id":{"type":"string","format":"uuid","description":"Fresh identity for this browser runtime; reuse only for retries of this claim."},"expected_runtime_id":{"type":"string","format":"uuid","nullable":true,"description":"Owner returned by GET session.runtimeOwnerId; null when never claimed."},"attempt":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"Fresh session with runtimeMode (record or review)","content":{"application/json":{"schema":{"type":"object","required":["session"],"properties":{"session":{"type":"object","additionalProperties":true,"required":["runtimeMode"],"properties":{"runtimeMode":{"type":"string","enum":["record","review"]},"runtimeOwnerId":{"type":"string","nullable":true,"format":"uuid"}}}}}}}},"400":{"description":"INVALID_REQUEST: malformed claim"},"401":{"description":"Missing, invalid or expired credentials"},"404":{"description":"Session not found in the authenticated tenant"},"409":{"description":"RUNTIME_PROTOCOL_NOT_ENABLED, RUNTIME_SUPERSEDED or ATTEMPT_SUPERSEDED; reload rather than overwriting the current owner"},"503":{"description":"Backend unavailable; no runtime was acknowledged"}}},"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Sessions"],"summary":"Fetch session details (requires API key or launch token)","description":"Retrieve detailed information about a SCORM session, including CMI data, progress, and package information.\n\n**Authentication:**\n- Requires API key (`X-API-Key` header) OR\n- Launch token (`Authorization: Bearer <token>` header or `token` query parameter)\n\n**Session Data:**\n- CMI data (SCORM-specific data)\n- Completion and success status\n- Score (scaled or raw)\n- Session time (ISO 8601 duration)\n- Attempt count\n- Suspend data (for resuming)\n\n**Example:**\n```bash\n# Using API key\ncurl -H \"X-API-Key: your-api-key\" \\\n  https://app.allureconnect.com/api/v1/sessions/{sessionId}\n\n# Using launch token\ncurl -H \"Authorization: Bearer <launch-token>\" \\\n  https://app.allureconnect.com/api/v1/sessions/{sessionId}\n```","operationId":"getSession","security":[{"ApiKeyAuth":[]},{"LaunchToken":[]}],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Session identifier"},{"name":"token","in":"query","required":false,"schema":{"type":"string"},"description":"Launch token (alternative to Authorization header)"}],"responses":{"200":{"description":"Session detail payload","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Rate limit (requests per minute)"},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in current window"},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when rate limit resets"}},"content":{"application/json":{"schema":{"type":"object","properties":{"interaction_report":{"type":"object","description":"Bounded read-only projection of retained CMI, not full attempt history or skill/mastery evidence. No new data is persisted. package_version and sco_id are unknown; reported_scorm_version is active-package metadata and is not historical provenance. Raw answer fields are sensitive learner data.","properties":{"schema_version":{"type":"integer","enum":[1]},"source":{"type":"string","enum":["retained_cmi_snapshot"]},"status":{"type":"string","enum":["available","empty","partial","unavailable"]},"scope":{"type":"object","properties":{"session_id":{"type":"string"},"package_id":{"type":"string"},"package_version":{"type":["string","null"],"description":"Always null: historical package version is not established by retained CMI."},"sco_id":{"type":["string","null"],"description":"Always null: a flattened session snapshot does not establish a SCO boundary."},"session_revision":{"type":"integer"},"reported_scorm_version":{"type":["string","null"],"enum":["1.2","2004",null]}}},"declared_count":{"type":["integer","null"]},"returned_count":{"type":"integer","maximum":200},"issues":{"type":"array","items":{"type":"string"},"description":"Partial/ambiguous data and bounds are explicit. Missing count is unknown, not proof of completeness."},"items":{"type":"array","maxItems":200,"items":{"type":"object","properties":{"index":{"type":"integer"},"id":{"type":["string","null"]},"type":{"type":["string","null"]},"description":{"type":["string","null"],"maxLength":4096,"description":"Retained question description, normally supplied by SCORM2004; preserved regardless of current package metadata. Null for missing or oversized text. No question-bank inference."},"response":{"type":["string","null"],"description":"Empty answer is preserved. Conflicting SCORM aliases return null."},"result":{"type":"string","enum":["correct","incorrect","neutral","unanticipated","numeric","unknown"]},"result_raw":{"type":["string","null"]},"numeric_result":{"type":["number","null"]},"weighting":{"type":["number","null"]},"time_raw":{"type":["string","null"]},"latency_raw":{"type":["string","null"]},"evidence_classification":{"type":"string","enum":["unclassified"],"description":"No assessment/practice intent, mastery or credit inferred."}}}}}},"session":{"allOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"attempts":{"type":"integer","nullable":true,"description":"Current attempt number (alias of `attempt_number`)."},"attempt_number":{"type":"integer","minimum":1,"description":"Current attempt number; status, score and time describe this attempt."},"launch_mode":{"type":"string","enum":["normal","review"],"description":"`review` when the hosted player opens a completed attempt read-only (cmi.mode=review)."},"start_over_allowed":{"type":"boolean","description":"Whether the hosted player offers \"Start over\" for the current attempt."},"attempt_history":{"type":"array","description":"Session detail only: up to 20 attempts, newest first. Earlier attempts keep their results after a retake or reset.","items":{"type":"object","properties":{"attempt_number":{"type":"integer"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","additionalProperties":true},"time_spent_seconds":{"type":"number"},"progress_percent":{"type":"number"},"started_at":{"type":"string","format":"date-time"},"last_activity_at":{"type":"string","format":"date-time"},"superseded_at":{"type":"string","format":"date-time","nullable":true},"superseded_reason":{"type":"string","nullable":true,"enum":["learner_start_over","launch_new_attempt","relaunch_policy","dashboard_reset","api_reset",null]}}}},"cmi_data":{"type":"object","additionalProperties":true},"suspend_data":{"type":"string","nullable":true},"version":{"type":"integer","minimum":1,"description":"Optimistic-locking revision. Increments on each committed update; pass the latest value back as `version` in PUT to detect concurrent writes."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","nullable":true}}},{"type":"object","properties":{"runtimeProtocol":{"type":"string","enum":["legacy","exclusive_v1"],"description":"Server launch policy; only exclusive_v1 sessions may claim a runtime."},"runtimeOwnerId":{"type":"string","format":"uuid","nullable":true,"description":"Current attempt runtime owner, or null before any claim."},"package":{"type":"object","required":["id","tenantId","slug","title","contentType","status","currentVersion","launchCount30d","storageMb","updatedAt"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"contentType":{"type":"string","enum":["scorm","vr_apk"]},"status":{"type":"string","enum":["draft","processing","ready","failed","archived"]},"currentVersion":{"type":"string"},"launchCount30d":{"type":"number"},"launchesRolling30d":{"type":"number"},"storageMb":{"type":"number"},"updatedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time","nullable":true},"deletionRequestedAt":{"type":"string","format":"date-time","nullable":true},"deletedAt":{"type":"string","format":"date-time","nullable":true},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"source":{"type":"string","enum":["upload","api","lms-sync"]},"demoWatermark":{"type":"boolean"},"sandboxExpiresAt":{"type":"string","format":"date-time","nullable":true},"sandboxExpired":{"type":"boolean"},"freePlanExpired":{"type":"boolean"},"connectMeteringEligible":{"type":"boolean"},"createLifecycleManaged":{"type":"boolean"},"createDeliveryAllowed":{"type":"boolean"},"createDeliveryDenialCode":{"type":"string","nullable":true}},"example":{"id":"pkg_abc123","tenantId":"tenant_example-workspace","slug":"workplace-safety-essentials","title":"Workplace Safety Essentials","contentType":"scorm","status":"ready","currentVersion":"1.2","launchCount30d":18,"launchesRolling30d":18,"storageMb":5,"updatedAt":"2026-09-01T12:00:00.000Z"}},"tenant":{"type":"object","description":"Tenant profile metadata","additionalProperties":true},"preferences":{"type":"object","additionalProperties":true}}}]},"preferences":{"type":"object","additionalProperties":true}}}}}},"401":{"description":"Unauthorized (missing or invalid API key/token)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden (tenant mismatch or insufficient permissions)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Transient backend failure. Retry after the delay in Retry-After.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0},"description":"Seconds to wait before retrying the request","example":5}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"examples":{"backendUnavailable":{"value":{"error":"The learning record backend is temporarily unavailable. Retry the request.","code":"BACKEND_UNAVAILABLE","retryable":true}}}}}}}},"put":{"tags":["Sessions"],"summary":"Update session CMI data","description":"Update CMI (Computer Managed Instruction) data for a SCORM session. Optimistic locking is available and is opt-in per request via `version`.\n\n**Optimistic Locking (opt-in):**\n- Each session has a version number that increments on each update\n- **Send `version`** to enable conflict detection: a stale value fails with 409 VERSION_CONFLICT, and you retry with exponential backoff\n- Use the `version` from the latest session read (`session.version`, also mirrored as the root `version`)\n- **Omit `version`** only for best-effort unload: revision comparison is skipped, but runtime ownership and attempt fencing remain mandatory. RUNTIME_SUPERSEDED and ATTEMPT_SUPERSEDED must stop the writer; never rebase these errors.\n\n**CMI Data:**\n- `cmi_data`: Raw CMI data object (SCORM-specific)\n- `completion_status`: not_attempted, incomplete, completed, passed, failed\n- `success_status`: unknown, passed, failed\n- `score`: Scaled (0-1) or raw score with min/max\n- `session_time`: ISO 8601 duration (e.g., PT1H30M)\n- `suspend_data`: Serialized suspend data for resuming\n\n**Error Handling:**\n- 409 Conflict: Version conflict — retry with the updated version. Only possible when you send `version`\n- 503 Service Unavailable: Retryable backend failure — honor the `Retry-After` header\n- Implement exponential backoff for retries\n- Maximum 3 retries recommended\n\n**Example:**\n```bash\ncurl -X PUT https://app.allureconnect.com/api/v1/sessions/{sessionId} \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"completion_status\": \"completed\",\n    \"success_status\": \"passed\",\n    \"score\": {\n      \"scaled\": 0.95,\n      \"raw\": 95,\n      \"min\": 0,\n      \"max\": 100\n    },\n    \"session_time\": \"PT1H30M\"\n  }'\n```","operationId":"updateSession","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"runtime_id":{"type":"string","format":"uuid","description":"Required with attempt for every write after a runtime claim, including unload; a superseded or review writer is rejected."},"cmi_data":{"type":"object","additionalProperties":true},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":0,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"session_time":{"type":"string","description":"ISO 8601 duration, e.g., PT35M42S"},"suspend_data":{"type":"string"},"attempt":{"type":"integer","minimum":1,"description":"Optional. The attempt number the writer loaded. If a retake or reset has replaced it, the write fails with 409 ATTEMPT_SUPERSEDED instead of touching the new attempt. Completed/passed never regresses within an attempt; start a new attempt to let a learner redo the course."},"version":{"type":"integer","minimum":1,"description":"Optional expected revision. A stale revision returns 409 VERSION_CONFLICT. Omitting version skips only revision comparison; it never bypasses runtime ownership or attempt fencing. Claimed-session unload writes still require matching runtime_id and attempt. Never rebase or retry writes after RUNTIME_SUPERSEDED or ATTEMPT_SUPERSEDED."}}},"examples":{"updateProgress":{"value":{"completion_status":"incomplete","session_time":"PT35M42S","cmi_data":{"cmi.core.lesson_status":"incomplete","cmi.core.score.raw":75,"cmi.core.score.max":100}}},"completeSession":{"value":{"completion_status":"completed","success_status":"passed","score":{"scaled":0.95,"raw":95,"min":0,"max":100},"session_time":"PT1H30M"}}}}}},"responses":{"200":{"description":"Update acknowledgement","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Rate limit (requests per minute)"},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in current window"},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when rate limit resets"}},"content":{"application/json":{"schema":{"type":"object","description":"Write confirmation plus the full post-write session. The canonical representation is the nested `session` object; the snake_case root fields mirror it as compatibility aliases for SCORM/LMS adapters. Either way a client can persist the result of a PUT without a follow-up GET.","properties":{"success":{"type":"boolean"},"session_id":{"type":"string","format":"uuid"},"updated_at":{"type":"string","format":"date-time"},"session":{"type":"object","additionalProperties":true,"description":"Canonical post-write session in the camelCase player shape (`cmiData`, `suspendData`, `completionStatus`, `timeSpentSeconds`, …). Read `session.version` for the revision to send on the next PUT.","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"integer","minimum":1,"description":"Revision after this write. Pass as `version` on the next PUT."}}},"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"learner_id":{"type":"string","description":"Alias of `user_id`."},"learner_name":{"type":"string","nullable":true},"status":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"progress_percent":{"type":"number","nullable":true},"progress":{"type":"number","nullable":true,"description":"Alias of `progress_percent` (0–100) for LMS adapters that read `progress`."},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"cmi_data":{"type":"object","additionalProperties":true},"cmi":{"type":"object","additionalProperties":true,"description":"Alias of `cmi_data` for LMS adapters that expect `cmi`."},"suspend_data":{"type":"string","nullable":true},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"time_spent_seconds":{"type":"integer","nullable":true},"time_seconds":{"type":"integer","nullable":true,"description":"Alias of `time_spent_seconds`."},"attempts":{"type":"integer","nullable":true},"version":{"type":"integer","minimum":1,"description":"Revision after this write. Pass it as `version` on the next PUT."},"launch_url":{"type":"string","format":"uri","nullable":true},"manifest_url":{"type":"string","format":"uri","nullable":true},"created_at":{"type":"string","format":"date-time"},"lesson_location":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.lesson_location` / `cmi.location`."},"entry":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.entry` / `cmi.entry`."},"exit":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.exit` / `cmi.exit`."},"scorm_version":{"type":"string","nullable":true}}},"examples":{"success":{"value":{"success":true,"session_id":"550e8400-e29b-41d4-a716-446655440000","updated_at":"2025-01-15T10:30:00.000Z"}}}}}},"409":{"description":"VERSION_CONFLICT permits a fresh revision retry. RUNTIME_SUPERSEDED or ATTEMPT_SUPERSEDED must stop this writer; never rebase stale CMI.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"examples":{"runtimeSuperseded":{"value":{"error":"This learning runtime has been replaced.","code":"RUNTIME_SUPERSEDED","current_attempt":1,"current_version":5}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Transient backend failure. Retry after the delay in Retry-After.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0},"description":"Seconds to wait before retrying the request","example":5}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"examples":{"backendUnavailable":{"value":{"error":"The learning record backend is temporarily unavailable. Retry the request.","code":"BACKEND_UNAVAILABLE","retryable":true}}}}}}}}},"/api/v1/sessions/{sessionId}/reset":{"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["Sessions"],"summary":"Reset a learner session (mark incomplete / retake)","description":"Starts a NEW attempt on the session with fresh status, score, suspend data and time, for example after an LMS admin resets course progress. The previous attempt keeps its completion, score and time in `attempt_history` and reports. Scoped to the API key's workspace and mode. Records a `session.reset` audit event (actor, reason, previous state) that is delivered to `sessions` webhooks. `reset: false` means the current attempt was already untouched.","operationId":"resetSession","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"reason":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"Session after the reset (same shape as the PUT response) plus `reset`","content":{"application/json":{"schema":{"allOf":[{"type":"object","description":"Write confirmation plus the full post-write session. The canonical representation is the nested `session` object; the snake_case root fields mirror it as compatibility aliases for SCORM/LMS adapters. Either way a client can persist the result of a PUT without a follow-up GET.","properties":{"success":{"type":"boolean"},"session_id":{"type":"string","format":"uuid"},"updated_at":{"type":"string","format":"date-time"},"session":{"type":"object","additionalProperties":true,"description":"Canonical post-write session in the camelCase player shape (`cmiData`, `suspendData`, `completionStatus`, `timeSpentSeconds`, …). Read `session.version` for the revision to send on the next PUT.","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"integer","minimum":1,"description":"Revision after this write. Pass as `version` on the next PUT."}}},"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"learner_id":{"type":"string","description":"Alias of `user_id`."},"learner_name":{"type":"string","nullable":true},"status":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"progress_percent":{"type":"number","nullable":true},"progress":{"type":"number","nullable":true,"description":"Alias of `progress_percent` (0–100) for LMS adapters that read `progress`."},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"cmi_data":{"type":"object","additionalProperties":true},"cmi":{"type":"object","additionalProperties":true,"description":"Alias of `cmi_data` for LMS adapters that expect `cmi`."},"suspend_data":{"type":"string","nullable":true},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"time_spent_seconds":{"type":"integer","nullable":true},"time_seconds":{"type":"integer","nullable":true,"description":"Alias of `time_spent_seconds`."},"attempts":{"type":"integer","nullable":true},"version":{"type":"integer","minimum":1,"description":"Revision after this write. Pass it as `version` on the next PUT."},"launch_url":{"type":"string","format":"uri","nullable":true},"manifest_url":{"type":"string","format":"uri","nullable":true},"created_at":{"type":"string","format":"date-time"},"lesson_location":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.lesson_location` / `cmi.location`."},"entry":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.entry` / `cmi.entry`."},"exit":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.exit` / `cmi.exit`."},"scorm_version":{"type":"string","nullable":true}}},{"type":"object","properties":{"reset":{"type":"boolean"}}}]}}}},"400":{"description":"Invalid session ID or body","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Session not found in this workspace/mode","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/sessions/{sessionId}/start-over":{"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["Sessions"],"summary":"Learner \"Start over\" from the hosted player","description":"Called by the hosted player with the learner's launch token for this session. Off by default: allowed only when the course or dispatch opts in to the player's Start over, and only once the current attempt is completed, passed or failed. Starts a new attempt; the finished one stays in history. Integrations should use `/reset` or `new_attempt`.","operationId":"startSessionOver","security":[{"LaunchToken":[]}],"responses":{"200":{"description":"Session after the new attempt started, plus `reset`","content":{"application/json":{"schema":{"type":"object","description":"Write confirmation plus the full post-write session. The canonical representation is the nested `session` object; the snake_case root fields mirror it as compatibility aliases for SCORM/LMS adapters. Either way a client can persist the result of a PUT without a follow-up GET.","properties":{"success":{"type":"boolean"},"session_id":{"type":"string","format":"uuid"},"updated_at":{"type":"string","format":"date-time"},"session":{"type":"object","additionalProperties":true,"description":"Canonical post-write session in the camelCase player shape (`cmiData`, `suspendData`, `completionStatus`, `timeSpentSeconds`, …). Read `session.version` for the revision to send on the next PUT.","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"integer","minimum":1,"description":"Revision after this write. Pass as `version` on the next PUT."}}},"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"user_id":{"type":"string"},"learner_id":{"type":"string","description":"Alias of `user_id`."},"learner_name":{"type":"string","nullable":true},"status":{"type":"string"},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"progress_percent":{"type":"number","nullable":true},"progress":{"type":"number","nullable":true,"description":"Alias of `progress_percent` (0–100) for LMS adapters that read `progress`."},"score":{"type":"object","properties":{"scaled":{"type":"number","nullable":true},"raw":{"type":"number","nullable":true},"min":{"type":"number","nullable":true},"max":{"type":"number","nullable":true}}},"cmi_data":{"type":"object","additionalProperties":true},"cmi":{"type":"object","additionalProperties":true,"description":"Alias of `cmi_data` for LMS adapters that expect `cmi`."},"suspend_data":{"type":"string","nullable":true},"session_time":{"type":"string","nullable":true,"description":"ISO 8601 duration (PT1H10M)"},"time_spent_seconds":{"type":"integer","nullable":true},"time_seconds":{"type":"integer","nullable":true,"description":"Alias of `time_spent_seconds`."},"attempts":{"type":"integer","nullable":true},"version":{"type":"integer","minimum":1,"description":"Revision after this write. Pass it as `version` on the next PUT."},"launch_url":{"type":"string","format":"uri","nullable":true},"manifest_url":{"type":"string","format":"uri","nullable":true},"created_at":{"type":"string","format":"date-time"},"lesson_location":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.lesson_location` / `cmi.location`."},"entry":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.entry` / `cmi.entry`."},"exit":{"type":"string","nullable":true,"description":"Convenience read of `cmi.core.exit` / `cmi.exit`."},"scorm_version":{"type":"string","nullable":true}}}}}},"401":{"description":"Missing or invalid launch token for this session","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"START_OVER_NOT_ALLOWED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/sessions/{sessionId}/refresh-token":{"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["Sessions"],"summary":"Refresh a SCORM session bearer token","description":"Mint a fresh bearer token for the same active session and return a tokenized `launch_url`. SCORM players should call this before token expiry. LMS reopen should embed the returned `launch_url` (or call POST /api/v1/packages/{id}/launch with the existing session_id) rather than loading package content HTML directly.","operationId":"refreshSessionToken","security":[{"LaunchToken":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Fresh session bearer token","content":{"application/json":{"schema":{"type":"object","required":["success","session_id","token","expires_in_seconds","launch_url"],"properties":{"success":{"type":"boolean"},"session_id":{"type":"string","format":"uuid"},"token":{"type":"string","description":"Fresh bearer token for the same SCORM session."},"expires_in_seconds":{"type":"integer","description":"Effective token TTL after platform min/max clamping."},"launch_url":{"type":"string","format":"uri","description":"Hosted player URL for this session with the fresh token already in `?token=`. LMS reopen must embed this URL (or relaunch with `session_id`); do not load package `launcher.html` as a substitute."}}}}}},"400":{"description":"Invalid session ID","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Missing, invalid, or expired-beyond-grace token","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Session not found for caller","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Transient backend failure. Retry after the delay in Retry-After.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0},"description":"Seconds to wait before retrying the request","example":5}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}},"examples":{"backendUnavailable":{"value":{"error":"The learning record backend is temporarily unavailable. Retry the request.","code":"BACKEND_UNAVAILABLE","retryable":true}}}}}}}}},"/api/v1/xapi/statements":{"post":{"tags":["xAPI"],"summary":"Store xAPI statement(s)","operationId":"storeXAPIStatements","description":"Store one or more xAPI statements following xAPI 1.0.3. An identical retry of a statement ID is idempotent; changed content under the same ID returns 409 STATEMENT_CONFLICT.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["actor","verb","object"],"description":"xAPI Statement (Experience API 1.0.3)","properties":{"id":{"type":"string","description":"Caller-supplied statement identifier or generated UUID."},"actor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"verb":{"type":"object","required":["id"],"description":"xAPI Verb","properties":{"id":{"type":"string","format":"uri","description":"Verb IRI"},"display":{"type":"object","description":"Language map for verb display","additionalProperties":{"type":"string"}}}},"object":{"type":"object","required":["id"],"description":"xAPI Activity Object","properties":{"objectType":{"type":"string","enum":["Activity"]},"id":{"type":"string","format":"uri","description":"Activity IRI"},"definition":{"type":"object","properties":{"name":{"type":"object","additionalProperties":{"type":"string"}},"description":{"type":"object","additionalProperties":{"type":"string"}},"type":{"type":"string","format":"uri"},"moreInfo":{"type":"string","format":"uri"},"extensions":{"type":"object","additionalProperties":true}}}}},"result":{"type":"object","description":"xAPI Result","properties":{"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":-1,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"success":{"type":"boolean"},"completion":{"type":"boolean"},"response":{"type":"string"},"duration":{"type":"string","description":"ISO 8601 duration"},"extensions":{"type":"object","additionalProperties":true}}},"context":{"type":"object","description":"xAPI Context","properties":{"registration":{"type":"string","format":"uuid"},"instructor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"team":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"platform":{"type":"string"},"language":{"type":"string"},"extensions":{"type":"object","additionalProperties":true}}},"timestamp":{"type":"string","format":"date-time"},"stored":{"type":"string","format":"date-time"},"authority":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"version":{"type":"string","enum":["1.0.0","1.0.1","1.0.2","1.0.3"]}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","actor":{"name":"John Doe","mbox":"mailto:john@example.com"},"verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"en-US":"completed"}},"object":{"id":"https://allureconnect.com/packages/abc-123","definition":{"name":{"en-US":"Introduction to JavaScript"},"type":"http://adlnet.gov/expapi/activities/course"}},"result":{"score":{"scaled":0.95,"raw":95,"min":0,"max":100},"success":true,"completion":true,"duration":"PT1H30M"},"timestamp":"2025-01-01T12:00:00Z"}},{"type":"array","items":{"type":"object","required":["actor","verb","object"],"description":"xAPI Statement (Experience API 1.0.3)","properties":{"id":{"type":"string","description":"Caller-supplied statement identifier or generated UUID."},"actor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"verb":{"type":"object","required":["id"],"description":"xAPI Verb","properties":{"id":{"type":"string","format":"uri","description":"Verb IRI"},"display":{"type":"object","description":"Language map for verb display","additionalProperties":{"type":"string"}}}},"object":{"type":"object","required":["id"],"description":"xAPI Activity Object","properties":{"objectType":{"type":"string","enum":["Activity"]},"id":{"type":"string","format":"uri","description":"Activity IRI"},"definition":{"type":"object","properties":{"name":{"type":"object","additionalProperties":{"type":"string"}},"description":{"type":"object","additionalProperties":{"type":"string"}},"type":{"type":"string","format":"uri"},"moreInfo":{"type":"string","format":"uri"},"extensions":{"type":"object","additionalProperties":true}}}}},"result":{"type":"object","description":"xAPI Result","properties":{"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":-1,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"success":{"type":"boolean"},"completion":{"type":"boolean"},"response":{"type":"string"},"duration":{"type":"string","description":"ISO 8601 duration"},"extensions":{"type":"object","additionalProperties":true}}},"context":{"type":"object","description":"xAPI Context","properties":{"registration":{"type":"string","format":"uuid"},"instructor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"team":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"platform":{"type":"string"},"language":{"type":"string"},"extensions":{"type":"object","additionalProperties":true}}},"timestamp":{"type":"string","format":"date-time"},"stored":{"type":"string","format":"date-time"},"authority":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"version":{"type":"string","enum":["1.0.0","1.0.1","1.0.2","1.0.3"]}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","actor":{"name":"John Doe","mbox":"mailto:john@example.com"},"verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"en-US":"completed"}},"object":{"id":"https://allureconnect.com/packages/abc-123","definition":{"name":{"en-US":"Introduction to JavaScript"},"type":"http://adlnet.gov/expapi/activities/course"}},"result":{"score":{"scaled":0.95,"raw":95,"min":0,"max":100},"success":true,"completion":true,"duration":"PT1H30M"},"timestamp":"2025-01-01T12:00:00Z"}}}]}}}},"responses":{"201":{"description":"Statement(s) stored","headers":{"X-Experience-API-Version":{"schema":{"type":"string"},"description":"xAPI version (1.0.3)"}},"content":{"application/json":{"schema":{"type":"object","required":["success","statement_ids"],"properties":{"success":{"type":"boolean","const":true},"statement_ids":{"type":"array","items":{"type":"string"}}}}}}},"400":{"description":"Invalid statement format","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"STATEMENT_CONFLICT: the statement ID already has different content","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"get":{"tags":["xAPI"],"summary":"Query xAPI statements","operationId":"queryXAPIStatements","description":"Query visible xAPI statements with filters, newest first. Private native-form rows are excluded. To read every statement, follow pagination.nextCursor until it is null: each request is one bounded read, so this works for a workspace of any size. page and the exact total/totalPages remain available whenever the workspace (or the slice selected by session_id, activity_id, package_id or statement_id) fits in one read of 10,000 raw rows / 8 MiB. Beyond that pagination.truncated is true, total/totalPages describe only the newest window, and ORDER CHANGES: statements are ordered by when they were first stored (creation), not by their stored timestamp, so a statement stored again later (for example a SCORM completion re-stored during a long session) keeps its original place instead of moving to the top. Requests that carry a cursor are rate limited per API key (default 300 per minute, 429 RATE_LIMIT_EXCEEDED); requests without one are not.","parameters":[{"name":"statement_id","in":"query","schema":{"type":"string"},"description":"Filter by specific statement ID"},{"name":"actor_mbox","in":"query","schema":{"type":"string"},"description":"Filter by bare actor email (for example, learner@example.com)"},{"name":"verb_id","in":"query","schema":{"type":"string","format":"uri"},"description":"Filter by verb IRI"},{"name":"activity_id","in":"query","schema":{"type":"string","format":"uri"},"description":"Filter by activity IRI"},{"name":"session_id","in":"query","schema":{"type":"string"},"description":"Filter by Connect session ID"},{"name":"package_id","in":"query","schema":{"type":"string"},"description":"Filter by Connect package ID"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"default":25,"maximum":500},"description":"Results per page (default: 25). A page holds at most 100 statements; values from 101 to 500 are accepted and return 100."},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Continuation from a previous response (pagination.nextCursor). Takes precedence over page. Send the same filters as the request that returned it. Returns 400 INVALID_CURSOR when it is malformed or altered, was issued to another workspace or for other filters, or was issued while the workspace still fit in one read and it no longer does; start the walk again without it."}],"responses":{"200":{"description":"xAPI statements list","content":{"application/json":{"schema":{"type":"object","required":["statements","pagination"],"properties":{"statements":{"type":"array","items":{"type":"object","required":["actor","verb","object"],"description":"xAPI Statement (Experience API 1.0.3)","properties":{"id":{"type":"string","description":"Caller-supplied statement identifier or generated UUID."},"actor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"verb":{"type":"object","required":["id"],"description":"xAPI Verb","properties":{"id":{"type":"string","format":"uri","description":"Verb IRI"},"display":{"type":"object","description":"Language map for verb display","additionalProperties":{"type":"string"}}}},"object":{"type":"object","required":["id"],"description":"xAPI Activity Object","properties":{"objectType":{"type":"string","enum":["Activity"]},"id":{"type":"string","format":"uri","description":"Activity IRI"},"definition":{"type":"object","properties":{"name":{"type":"object","additionalProperties":{"type":"string"}},"description":{"type":"object","additionalProperties":{"type":"string"}},"type":{"type":"string","format":"uri"},"moreInfo":{"type":"string","format":"uri"},"extensions":{"type":"object","additionalProperties":true}}}}},"result":{"type":"object","description":"xAPI Result","properties":{"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":-1,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"success":{"type":"boolean"},"completion":{"type":"boolean"},"response":{"type":"string"},"duration":{"type":"string","description":"ISO 8601 duration"},"extensions":{"type":"object","additionalProperties":true}}},"context":{"type":"object","description":"xAPI Context","properties":{"registration":{"type":"string","format":"uuid"},"instructor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"team":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"platform":{"type":"string"},"language":{"type":"string"},"extensions":{"type":"object","additionalProperties":true}}},"timestamp":{"type":"string","format":"date-time"},"stored":{"type":"string","format":"date-time"},"authority":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"version":{"type":"string","enum":["1.0.0","1.0.1","1.0.2","1.0.3"]}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","actor":{"name":"John Doe","mbox":"mailto:john@example.com"},"verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"en-US":"completed"}},"object":{"id":"https://allureconnect.com/packages/abc-123","definition":{"name":{"en-US":"Introduction to JavaScript"},"type":"http://adlnet.gov/expapi/activities/course"}},"result":{"score":{"scaled":0.95,"raw":95,"min":0,"max":100},"success":true,"completion":true,"duration":"PT1H30M"},"timestamp":"2025-01-01T12:00:00Z"}}},"pagination":{"type":"object","required":["page","limit","total","totalPages"],"properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"truncated":{"type":"boolean","description":"True when the result reflects only a bounded most-recent slice (up to 10,000 raw rows / 8 MiB). Totals then describe that slice, not the complete tenant history; follow nextCursor for the rest. Private learner rows are excluded."},"nextCursor":{"type":["string","null"],"description":"Sealed continuation: it cannot be read or altered, and it is valid only for the workspace and the filters of the request that returned it. Pass it back as the cursor query parameter to read the next page; null means there is nothing more to read. A page may hold fewer statements than limit (even none) while nextCursor is still set."}}}}}}}},"400":{"description":"INVALID_PAGE, INVALID_LIMIT or INVALID_CURSOR","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED: too many continuation requests from this API key (X-RateLimit-* and Retry-After headers)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/xapi/statements/{id}":{"get":{"tags":["xAPI"],"summary":"Get xAPI statement by ID","operationId":"getXAPIStatement","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Statement ID"}],"responses":{"200":{"description":"xAPI statement","headers":{"X-Experience-API-Version":{"schema":{"type":"string"},"description":"xAPI version (1.0.3)"}},"content":{"application/json":{"schema":{"type":"object","required":["actor","verb","object"],"description":"xAPI Statement (Experience API 1.0.3)","properties":{"id":{"type":"string","description":"Caller-supplied statement identifier or generated UUID."},"actor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"verb":{"type":"object","required":["id"],"description":"xAPI Verb","properties":{"id":{"type":"string","format":"uri","description":"Verb IRI"},"display":{"type":"object","description":"Language map for verb display","additionalProperties":{"type":"string"}}}},"object":{"type":"object","required":["id"],"description":"xAPI Activity Object","properties":{"objectType":{"type":"string","enum":["Activity"]},"id":{"type":"string","format":"uri","description":"Activity IRI"},"definition":{"type":"object","properties":{"name":{"type":"object","additionalProperties":{"type":"string"}},"description":{"type":"object","additionalProperties":{"type":"string"}},"type":{"type":"string","format":"uri"},"moreInfo":{"type":"string","format":"uri"},"extensions":{"type":"object","additionalProperties":true}}}}},"result":{"type":"object","description":"xAPI Result","properties":{"score":{"type":"object","properties":{"scaled":{"type":"number","minimum":-1,"maximum":1},"raw":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"}}},"success":{"type":"boolean"},"completion":{"type":"boolean"},"response":{"type":"string"},"duration":{"type":"string","description":"ISO 8601 duration"},"extensions":{"type":"object","additionalProperties":true}}},"context":{"type":"object","description":"xAPI Context","properties":{"registration":{"type":"string","format":"uuid"},"instructor":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"team":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"platform":{"type":"string"},"language":{"type":"string"},"extensions":{"type":"object","additionalProperties":true}}},"timestamp":{"type":"string","format":"date-time"},"stored":{"type":"string","format":"date-time"},"authority":{"type":"object","description":"xAPI Actor (Agent or Group)","properties":{"objectType":{"type":"string","enum":["Agent","Group"]},"name":{"type":"string"},"mbox":{"type":"string","format":"email","description":"Email in mailto: format"},"mbox_sha1sum":{"type":"string"},"openid":{"type":"string","format":"uri"},"account":{"type":"object","properties":{"homePage":{"type":"string","format":"uri"},"name":{"type":"string"}}}}},"version":{"type":"string","enum":["1.0.0","1.0.1","1.0.2","1.0.3"]}},"example":{"id":"550e8400-e29b-41d4-a716-446655440000","actor":{"name":"John Doe","mbox":"mailto:john@example.com"},"verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"en-US":"completed"}},"object":{"id":"https://allureconnect.com/packages/abc-123","definition":{"name":{"en-US":"Introduction to JavaScript"},"type":"http://adlnet.gov/expapi/activities/course"}},"result":{"score":{"scaled":0.95,"raw":95,"min":0,"max":100},"success":true,"completion":true,"duration":"PT1H30M"},"timestamp":"2025-01-01T12:00:00Z"}}}}},"404":{"description":"Statement not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/xapi/analytics/actors":{"get":{"tags":["xAPI"],"summary":"Get actor performance analytics","operationId":"getActorPerformance","description":"Retrieve aggregated performance metrics by actor, excluding private native-form outcomes. Totals are computed by reading the workspace's statements in bounded pages, so a 200 without allow_partial is always complete, for a workspace of any size. One request stops after 250,000 statements or about 20 seconds. If that budget is reached the request FAILS with 500 XAPI_ANALYTICS_INCOMPLETE, unless allow_partial=true was sent, in which case it returns 200 with incomplete: true, coverage and a continuation. Partial tables from separate continuations CANNOT be merged into exact totals: averages, unique counts, min_* filters, sort and pagination are all computed per segment; only the plain counts add up, and scored_count lets a client re-weight averages. When the workspace needs more than one bounded read, each request is a full pass over its statements: such passes are rate limited per API key (default 6 per minute, 429 RATE_LIMIT_EXCEEDED) and only the first 1,000 rows (page × limit) can be requested (400 ANALYTICS_PAGE_WINDOW_EXCEEDED). Workspaces that fit in one read are unaffected by both.","parameters":[{"name":"actor_mbox","in":"query","schema":{"type":"string","format":"email"},"description":"Filter by actor email"},{"name":"min_activities","in":"query","schema":{"type":"integer"},"description":"Minimum unique activities"},{"name":"sort","in":"query","schema":{"type":"string","enum":["total_statements","unique_activities","completed_count","passed_count","failed_count","avg_score_scaled","last_activity"]},"description":"Sort field"},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"description":"Sort order"},{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"default":25,"maximum":100},"description":"Results per page (default: 25, max: 100)"},{"name":"allow_partial","in":"query","schema":{"type":"string","enum":["true"]},"description":"Opt in to totals that do not cover the whole workspace. Without it, a request that cannot be completed fails with 500 XAPI_ANALYTICS_INCOMPLETE."},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"The continuation of a previous partial response; requires allow_partial=true. The totals then cover the next, older segment of statements only. 400 INVALID_CURSOR when it does not open for this workspace."}],"responses":{"200":{"description":"Actor performance data","content":{"application/json":{"schema":{"type":"object","properties":{"actors":{"type":"array","items":{"type":"object","description":"Aggregated performance metrics by actor","properties":{"tenant_id":{"type":"string","format":"uuid"},"actor_mbox":{"type":"string","format":"email"},"actor_name":{"type":"string"},"total_statements":{"type":"integer"},"unique_activities":{"type":"integer"},"completed_count":{"type":"integer"},"passed_count":{"type":"integer"},"failed_count":{"type":"integer"},"success_count":{"type":"integer"},"completion_count":{"type":"integer"},"avg_score_scaled":{"type":"number","nullable":true},"scored_count":{"type":"integer","description":"Number of statements behind avg_score_scaled."},"first_activity":{"type":"string","format":"date-time"},"last_activity":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}},"incomplete":{"type":"boolean","description":"False when the totals cover every statement in the workspace. True when the request budget was reached or the request started from a continuation."},"continuation":{"type":["string","null"],"description":"Pass as cursor to aggregate the next, older segment. Segments are disjoint: per-item counts can be added across segments; unique counts and averages cannot. Null when nothing older remains."},"scannedStatements":{"type":"integer","description":"Number of visible statements the totals were computed from."},"coverage":{"type":"string","description":"Present only on a partial answer: what the totals cover, in words."}}}}}},"400":{"description":"INVALID_CURSOR, or ANALYTICS_PAGE_WINDOW_EXCEEDED when page × limit exceeds 1,000 on a workspace that needs more than one read","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED: too many full analytics passes from this API key (X-RateLimit-* and Retry-After headers)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"500":{"description":"XAPI_ANALYTICS_INCOMPLETE: complete totals are not available within one request and allow_partial=true was not sent. Not retryable as is.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/xapi/analytics/activities":{"get":{"tags":["xAPI"],"summary":"Get activity performance analytics","operationId":"getActivityPerformance","description":"Retrieve aggregated performance metrics by activity, excluding private native-form outcomes. Totals are computed by reading the workspace's statements in bounded pages, so a 200 without allow_partial is always complete, for a workspace of any size. One request stops after 250,000 statements or about 20 seconds. If that budget is reached the request FAILS with 500 XAPI_ANALYTICS_INCOMPLETE, unless allow_partial=true was sent, in which case it returns 200 with incomplete: true, coverage and a continuation. Partial tables from separate continuations CANNOT be merged into exact totals: averages, unique counts, min_* filters, sort and pagination are all computed per segment; only the plain counts add up, and scored_count lets a client re-weight averages. When the workspace needs more than one bounded read, each request is a full pass over its statements: such passes are rate limited per API key (default 6 per minute, 429 RATE_LIMIT_EXCEEDED) and only the first 1,000 rows (page × limit) can be requested (400 ANALYTICS_PAGE_WINDOW_EXCEEDED). Workspaces that fit in one read are unaffected by both.","parameters":[{"name":"activity_id","in":"query","schema":{"type":"string","format":"uri"},"description":"Filter by activity IRI"},{"name":"activity_type","in":"query","schema":{"type":"string","format":"uri"},"description":"Filter by activity type"},{"name":"package_id","in":"query","schema":{"type":"string"},"description":"Filter by SCORM package"},{"name":"min_learners","in":"query","schema":{"type":"integer"},"description":"Minimum unique learners"},{"name":"sort","in":"query","schema":{"type":"string","enum":["total_statements","unique_learners","completed_count","passed_count","failed_count","avg_score_scaled","last_activity"]},"description":"Sort field"},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"description":"Sort order"},{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"default":25,"maximum":100},"description":"Results per page (default: 25, max: 100)"},{"name":"allow_partial","in":"query","schema":{"type":"string","enum":["true"]},"description":"Opt in to totals that do not cover the whole workspace. Without it, a request that cannot be completed fails with 500 XAPI_ANALYTICS_INCOMPLETE."},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"The continuation of a previous partial response; requires allow_partial=true. The totals then cover the next, older segment of statements only. 400 INVALID_CURSOR when it does not open for this workspace."}],"responses":{"200":{"description":"Activity performance data","content":{"application/json":{"schema":{"type":"object","properties":{"activities":{"type":"array","items":{"type":"object","description":"Aggregated performance metrics by activity","properties":{"tenant_id":{"type":"string","format":"uuid"},"activity_id":{"type":"string","format":"uri"},"activity_type":{"type":"string","format":"uri","nullable":true},"package_id":{"type":"string","format":"uuid","nullable":true},"total_statements":{"type":"integer"},"unique_learners":{"type":"integer"},"completed_count":{"type":"integer"},"passed_count":{"type":"integer"},"failed_count":{"type":"integer"},"success_count":{"type":"integer"},"completion_count":{"type":"integer"},"avg_score_scaled":{"type":"number","nullable":true},"scored_count":{"type":"integer","description":"Number of statements behind avg_score_scaled."},"first_activity":{"type":"string","format":"date-time"},"last_activity":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}},"incomplete":{"type":"boolean","description":"False when the totals cover every statement in the workspace. True when the request budget was reached or the request started from a continuation."},"continuation":{"type":["string","null"],"description":"Pass as cursor to aggregate the next, older segment. Segments are disjoint: per-item counts can be added across segments; unique counts and averages cannot. Null when nothing older remains."},"scannedStatements":{"type":"integer","description":"Number of visible statements the totals were computed from."},"coverage":{"type":"string","description":"Present only on a partial answer: what the totals cover, in words."}}}}}},"400":{"description":"INVALID_CURSOR, or ANALYTICS_PAGE_WINDOW_EXCEEDED when page × limit exceeds 1,000 on a workspace that needs more than one read","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"RATE_LIMIT_EXCEEDED: too many full analytics passes from this API key (X-RateLimit-* and Retry-After headers)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"500":{"description":"XAPI_ANALYTICS_INCOMPLETE: complete totals are not available within one request and allow_partial=true was not sent. Not retryable as is.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/organizations":{"get":{"tags":["Organizations"],"summary":"List organizations","description":"List account-level organization/customer groups for the authenticated tenant. Organizations are attribution filters only and do not change API key, dispatch launch, postback, or xAPI boundaries.","operationId":"listOrganizations","responses":{"200":{"description":"Organizations for the authenticated account.","content":{"application/json":{"schema":{"type":"object","required":["organizations"],"properties":{"organizations":{"type":"array","items":{"type":"object","required":["id","externalId","name","kind","status","createdAt","updatedAt"],"properties":{"id":{"type":"string","description":"Public organization identifier."},"externalId":{"type":"string","description":"Alias of id for forward compatibility."},"name":{"type":"string"},"kind":{"type":"string","enum":["internal","external"]},"status":{"type":"string","enum":["active","archived"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/dispatches":{"get":{"tags":["Dispatches"],"summary":"List dispatch packages","description":"List all dispatch packages for the authenticated tenant. Dispatch packages are lightweight SCORM shells for distributing to third-party LMSs.\n\n**Features:**\n- Returns all dispatch packages for the tenant\n- Includes package metadata and launch statistics\n\n**Example:**\n```bash\ncurl -H \"X-API-Key: your-api-key\" \\\n  https://app.allureconnect.com/api/v1/dispatches\n```","operationId":"listDispatches","parameters":[],"responses":{"200":{"description":"Returns a top-level dispatches array for the authenticated tenant.","content":{"application/json":{"schema":{"type":"object","required":["dispatches"],"properties":{"dispatches":{"type":"array","items":{"type":"object","required":["id","tenantId","label","packageId","status","destination","launches30d"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"label":{"type":"string"},"packageId":{"type":"string"},"status":{"type":"string","description":"Dispatch lifecycle status (e.g. active, paused, archived)."},"destination":{"type":"string","description":"Combined \"Customer · LMS\" destination string."},"organizationId":{"type":"string","nullable":true,"description":"Optional account-level organization attribution id."},"organizationName":{"type":"string","nullable":true,"description":"Resolved organization display name when assigned."},"launches30d":{"type":"integer"},"passwordProtected":{"type":"boolean"},"seatsUsed":{"type":"integer","nullable":true},"seatsCap":{"type":"integer","nullable":true},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"ISO expiry timestamp; null when the dispatch never expires."}}}}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Dispatches"],"summary":"Create a dispatch package","description":"Create a durable dispatch package for distributing SCORM content to third-party LMSs. Dispatch records produce stable hand-off URLs that look up the record at learner launch time and then mint short-lived player sessions internally.\n\n**Features:**\n- Returns a stable record-backed launch URL\n- Can be paired with a dispatch ZIP containing a SCORM manifest and redirect page\n- Supports record-level registration limits and expiration\n- Can restrict launches to specific domains\n- Completion callbacks use `postback_url` and require `postback_secret` for new integrations\n\n**Example:**\n```bash\ncurl -X POST https://app.allureconnect.com/api/v1/dispatches \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"package_id\": \"5c9476b4-2c7a-4c38-8d44-6f6f64d1bf12\",\n    \"dispatch_name\": \"Safety Course - External LMS\",\n    \"registration_limit\": 100,\n    \"expires_in_hours\": 720,\n    \"postback_url\": \"https://your-app.example.com/allure/completions\",\n    \"postback_secret\": \"replace-with-at-least-16-random-characters\"\n  }'\n```\n\nWhen `postback_url` is configured, Connect signs the raw JSON callback body with HMAC-SHA256 and sends `X-Connect-Signature: sha256=<hex>`. Receivers must fail closed when their expected secret is unset, the signature header is missing, or the signature is invalid.","operationId":"createDispatch","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["package_id"],"properties":{"package_id":{"type":"string","format":"uuid","description":"SCORM package ID to create dispatch for"},"dispatch_name":{"type":"string","description":"Name for the dispatch package"},"registration_limit":{"type":"integer","minimum":1,"description":"Maximum number of registrations (optional)"},"expires_in_hours":{"type":"integer","minimum":1,"description":"Expiration time in hours (optional)"},"allowed_domains":{"type":"array","items":{"type":"string"},"description":"Allowed domains for launch (optional)"},"postback_url":{"type":"string","format":"uri","description":"Completion callback URL. Requires postback_secret."},"postback_secret":{"type":"string","minLength":16,"maxLength":512,"description":"HMAC-SHA256 signing secret used for X-Connect-Signature. Required when postback_url is set."},"customer_name":{"type":"string","description":"Customer organization name (preferred). Must be paired with lms_name."},"organization_id":{"type":"string","nullable":true,"description":"Optional organization/customer group id for account-level usage and skill-readiness attribution."},"lms_name":{"type":"string","description":"Destination LMS name. Required when customer_name is set."},"client_name":{"type":"string","description":"Legacy combined destination (\"Customer · LMS\"). Prefer customer_name + lms_name."},"destination":{"type":"string","description":"Legacy alias for client_name."}}}}}},"responses":{"201":{"description":"Dispatch package created","content":{"application/json":{"schema":{"type":"object","properties":{"dispatch":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"organizationId":{"type":"string","nullable":true},"organization_id":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"organization_name":{"type":"string","nullable":true},"launchUrl":{"type":"string","format":"uri","example":"https://app.allureconnect.com/player/dispatch/dispatch_abc123xyz"},"launch_url":{"type":"string","format":"uri","example":"https://app.allureconnect.com/player/dispatch/dispatch_abc123xyz"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"expires_at":{"type":"string","format":"date-time","nullable":true},"registrationLimit":{"type":"integer","nullable":true},"registration_limit":{"type":"integer","nullable":true},"zip_url":{"type":"string","format":"uri","nullable":true}}},"dispatch_url":{"type":"string","format":"uri","example":"https://app.allureconnect.com/player/dispatch/dispatch_abc123xyz"},"dispatch_token":{"type":"string","description":"Legacy dispatch JWT for password-gated launches and older integrations. Do not use as the LMS handoff URL — persist dispatch_url / launchUrl (/player/dispatch/{dispatchId}) for SCORM ZIP and static embeds."},"expires_at":{"type":"string","format":"date-time","nullable":true}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Package lifecycle conflict: archived, processing, deletion pending, or deleted","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["PACKAGE_ARCHIVED","PACKAGE_NOT_READY","PACKAGE_DELETION_PENDING","PACKAGE_DELETED"]}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/{packageId}/dispatches":{"post":{"tags":["Dispatches"],"summary":"Create a package dispatch","description":"Create a durable dispatch record for one package. Use this for external LMS embeds that need a stable hand-off URL; use POST /api/v1/packages/{packageId}/launch for short-lived per-learner hosted playback sessions.","operationId":"createPackageDispatch","parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"},"description":"Package identifier to dispatch"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","description":"Human-readable dispatch label"},"destination":{"type":"string","description":"External LMS or audience destination"},"registration_limit":{"type":"integer","minimum":1,"description":"Maximum number of unique registrations"},"expires_in_hours":{"type":"integer","minimum":1,"description":"Record-level expiration window"},"allowed_domains":{"type":"array","items":{"type":"string"},"description":"Origins or domains allowed to launch this dispatch"},"organization_id":{"type":"string","nullable":true,"description":"Optional organization/customer group id for account-level attribution."}}}}}},"responses":{"201":{"description":"Dispatch package created","content":{"application/json":{"schema":{"type":"object","properties":{"dispatch":{"type":"object","properties":{"id":{"type":"string"},"packageId":{"type":"string"},"organizationId":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"launchUrl":{"type":"string","format":"uri","example":"https://app.allureconnect.com/player/dispatch/dispatch_abc123xyz"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"registrationLimit":{"type":"integer","nullable":true}}},"dispatch_url":{"type":"string","format":"uri","example":"https://app.allureconnect.com/player/dispatch/dispatch_abc123xyz"},"dispatch_token":{"type":"string","description":"Legacy dispatch JWT — not the LMS handoff URL. Use launchUrl / dispatch_url with a dispatch id path for embeds and ZIP export."},"expires_at":{"type":"string","format":"date-time","nullable":true}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Package lifecycle conflict: archived, processing, deletion pending, or deleted","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["PACKAGE_ARCHIVED","PACKAGE_NOT_READY","PACKAGE_DELETION_PENDING","PACKAGE_DELETED"]}}}}}}}}},"/api/v1/dispatches/{id}":{"patch":{"tags":["Dispatches"],"summary":"Update dispatch attribution and player settings","description":"Update the optional organization/customer-group attribution for a dispatch, and/or the hosted player's \"Start over\" override for sessions launched through it. This is additive and does not change the durable launch URL, SCORM ZIP behavior, postback settings, or xAPI/LRS flow.","operationId":"updateDispatchAttribution","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Dispatch package identifier"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"additionalProperties":false,"anyOf":[{"required":["organization_id"]},{"required":["organizationId"]},{"required":["learner_start_over_allowed"]}],"properties":{"organization_id":{"type":"string","nullable":true,"description":"Organization id to assign; null clears attribution."},"learner_start_over_allowed":{"type":"boolean","nullable":true,"description":"Show the hosted player's \"Start over\" button for sessions launched through this dispatch (overrides the course setting; null inherits it). Off by default: the LMS normally drives retakes via `new_attempt` or `POST /sessions/{id}/reset`."},"organizationId":{"type":"string","nullable":true,"description":"Camel-case alias of organization_id."}}}}}},"responses":{"200":{"description":"Updated dispatch package details","content":{"application/json":{"schema":{"type":"object","properties":{"dispatch":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string","nullable":true},"organization_id":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"organization_name":{"type":"string","nullable":true},"launch_url":{"type":"string","format":"uri"}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Dispatch or organization not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"get":{"tags":["Dispatches"],"summary":"Get dispatch package details","description":"Retrieve details for a specific dispatch package, including launch URL and statistics.","operationId":"getDispatch","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Dispatch package identifier"}],"responses":{"200":{"description":"Dispatch package details","content":{"application/json":{"schema":{"type":"object","properties":{"dispatch":{"type":"object","properties":{"id":{"type":"string"},"tenant_id":{"type":"string","format":"uuid"},"package_id":{"type":"string","format":"uuid"},"organizationId":{"type":"string","nullable":true},"organization_id":{"type":"string","nullable":true},"organizationName":{"type":"string","nullable":true},"organization_name":{"type":"string","nullable":true},"launch_url":{"type":"string","format":"uri"},"zip_url":{"type":"string","format":"uri","nullable":true},"registration_limit":{"type":"integer","nullable":true},"expires_at":{"type":"string","format":"date-time","nullable":true},"launch_count":{"type":"integer"},"last_launch":{"type":"string","format":"date-time","nullable":true}}}}}}}},"404":{"description":"Dispatch not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhooks","description":"List all webhooks registered for the authenticated tenant. Webhooks receive events when packages are processed, sessions are updated, etc.\n\n**Features:**\n- Returns all webhooks for the tenant\n- Includes webhook URL, event types, and delivery status\n- Shows retry policy and event filters\n\n**Example:**\n```bash\ncurl -H \"X-API-Key: your-api-key\" \\\n  https://app.allureconnect.com/api/v1/webhooks\n```","operationId":"listWebhooks","parameters":[{"name":"tenant_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Tenant context (defaults to API key tenant)"}],"responses":{"200":{"description":"List of webhooks","content":{"application/json":{"schema":{"type":"object","properties":{"endpoints":{"type":"array","description":"Registered webhook endpoints for the tenant.","items":{"type":"object","properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"label":{"type":"string"},"url":{"type":"string","format":"uri"},"status":{"type":"string","enum":["active","disabled"]},"eventScope":{"type":"string","enum":["packages","sessions","usage","dispatches","competency","all"]},"signingSecretConfigured":{"type":"boolean","description":"Whether a per-endpoint signing secret is configured. The secret itself is never returned."}}}},"deliveries":{"type":"array","description":"Recent delivery attempts across the tenant's endpoints.","items":{"type":"object","properties":{"id":{"type":"string"},"endpointId":{"type":"string"},"eventType":{"type":"string"},"status":{"type":"string","enum":["queued","delivered","failed","dead_letter"]},"attemptCount":{"type":"integer"},"lastAttemptAt":{"type":"string","format":"date-time"},"nextAttemptAt":{"type":"string","format":"date-time","nullable":true},"lastResponseCode":{"type":"integer","nullable":true},"lastError":{"type":"string","nullable":true},"lastResponseBody":{"type":"string","nullable":true,"description":"Truncated body of your endpoint's last HTTP response (max 500 chars) — useful for diagnosing why deliveries fail."},"deadLetteredAt":{"type":"string","format":"date-time","nullable":true}}}}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook","description":"Register a webhook to receive platform events. Webhooks are delivered via HTTP POST with HMAC signature verification.\n\n**Event scopes** (`eventScope`): `packages`, `sessions`, `usage`, `dispatches`, `competency`, or `all`.\n\n**Delivered event names:**\n- `package.launched`, `package.archived`, `package.version_activated`\n- `session.completed`, `session.failed`, `session.suspended`, `session.reset`\n- `usage.threshold_reached.70`, `usage.threshold_reached.80`, `usage.threshold_reached.90`, `usage.threshold_reached.100` (launch-time alerts fire at 80 and 100; 70 and 90 can still arrive from older alert sources)\n- `usage.spend_cap.80`, `usage.spend_cap.100` (customer-set spend cap alerts)\n- `dispatch.created`, `dispatch.paused`, `dispatch.resumed`, `dispatch.archived`\n- `dispatch.restored`, `dispatch.extended`, `dispatch.expired`, `dispatch.deleted`\n\n**Security:**\n- HMAC-SHA256 signature included in `X-Connect-Signature: sha256=<hex>`\n- Legacy-compatible `X-Allure-Signature` headers are also sent\n- Secret is required for new webhook endpoints and must be at least 16 characters\n- Verify the signature over the raw JSON request body\n\n**Example:**\n```bash\ncurl -X POST https://app.allureconnect.com/api/v1/webhooks \\\n  -H \"X-API-Key: your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"https://your-app.com/webhooks/scorm\",\n    \"secret\": \"replace-with-at-least-16-random-characters\",\n    \"label\": \"Production LMS\",\n    \"eventScope\": \"sessions\"\n  }'\n```","operationId":"createWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"anyOf":[{"required":["secret"]},{"required":["signingSecret"]}],"description":"At least one of `secret` or `signingSecret` must be provided — it is the per-endpoint HMAC-SHA256 signing key (16–512 characters). If both are provided, `signingSecret` takes precedence.","properties":{"url":{"type":"string","format":"uri","description":"Webhook URL to receive events"},"secret":{"type":"string","minLength":16,"maxLength":512,"description":"Secret for HMAC-SHA256 verification of X-Connect-Signature. Provide this or `signingSecret`."},"signingSecret":{"type":"string","minLength":16,"maxLength":512,"description":"Alternative name for `secret`; identical meaning. If both are provided, `signingSecret` takes precedence."},"label":{"type":"string","minLength":2,"maxLength":80,"description":"Human-readable endpoint label"},"eventScope":{"type":"string","enum":["packages","sessions","usage","dispatches","competency","all"],"default":"all","description":"Subscription scope for delivered events"}}},"examples":{"sessionEvents":{"value":{"url":"https://your-app.com/webhooks/scorm","secret":"replace-with-at-least-16-random-characters","label":"LMS session events","eventScope":"sessions"}}}}}},"responses":{"201":{"description":"Webhook created","content":{"application/json":{"schema":{"type":"object","required":["webhook","endpoint"],"properties":{"webhook":{"type":"object","required":["id","tenantId","label","url","status","eventScope"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"label":{"type":"string"},"url":{"type":"string","format":"uri"},"status":{"type":"string","enum":["active","disabled"]},"eventScope":{"type":"string","enum":["packages","sessions","usage","dispatches","competency","all"]},"mode":{"type":"string","enum":["live","test"]},"signingSecretConfigured":{"type":"boolean"}}},"endpoint":{"type":"object","description":"Compatibility alias of webhook.","required":["id","tenantId","label","url","status","eventScope"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"label":{"type":"string"},"url":{"type":"string","format":"uri"},"status":{"type":"string","enum":["active","disabled"]},"eventScope":{"type":"string","enum":["packages","sessions","usage","dispatches","competency","all"]},"mode":{"type":"string","enum":["live","test"]},"signingSecretConfigured":{"type":"boolean"}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/quotas":{"get":{"tags":["Quotas"],"summary":"Get quota usage and limits","description":"Retrieve current quota usage and operational limits for the authenticated tenant.\n\n**Features:**\n- Returns the same `usage` projection used by the signed-in dashboard\n- Includes package, storage, launch, webhook-failure, and active-learner counters\n- Includes the tenant's effective `max_upload_mb` ceiling\n\n**Example:**\n```bash\ncurl -H \"X-API-Key: your-api-key\" \\\n  https://app.allureconnect.com/api/v1/quotas\n```","operationId":"getQuotas","responses":{"200":{"description":"Quota usage and limits","content":{"application/json":{"schema":{"type":"object","required":["usage","max_upload_mb"],"properties":{"usage":{"type":"object","required":["tenantId","packageLimit","packageCount","storageLimitGb","storageUsedGb","monthlyLaunchLimit","monthlyLaunches","webhookFailureCount"],"properties":{"tenantId":{"type":"string"},"plan":{"type":"string"},"packageLimit":{"type":"number"},"packageCount":{"type":"number"},"storageLimitGb":{"type":"number"},"storageUsedGb":{"type":"number"},"monthlyLaunchLimit":{"type":"number"},"monthlyLaunches":{"type":"number"},"launchesRolling30d":{"type":"number"},"webhookFailureCount":{"type":"number"},"webhookFailureCountCapped":{"type":"boolean"},"includedActiveLearners":{"type":"number"},"activeLearners":{"type":"number"}}},"max_upload_mb":{"type":"number"}}},"examples":{"success":{"value":{"usage":{"tenantId":"tenant_example-workspace","plan":"growth","packageLimit":100,"packageCount":45,"storageLimitGb":50,"storageUsedGb":20,"monthlyLaunchLimit":10000,"monthlyLaunches":3200,"launchesRolling30d":3100,"webhookFailureCount":0,"webhookFailureCountCapped":false,"includedActiveLearners":1500,"activeLearners":420},"max_upload_mb":500}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/usage/pricing":{"get":{"tags":["Quotas"],"summary":"Get usage pricing summary","description":"Retrieve billing-aligned active learner usage for the authenticated tenant. Optional `user_id` or `learner_id` query params scope the response to one partner user for per-user reconciliation.","operationId":"getUsagePricing","parameters":[{"name":"user_id","in":"query","required":false,"schema":{"type":"string"},"description":"Partner user id passed when launching a package or dispatch."},{"name":"learner_id","in":"query","required":false,"schema":{"type":"string"},"description":"Learner id alias for integrations that store learner ids separately."},{"name":"workspace_external_id","in":"query","required":false,"schema":{"type":"string"},"description":"Partner workspace id echoed in the response scope for reconciliation."}],"responses":{"200":{"description":"Usage pricing summary","content":{"application/json":{"schema":{"type":"object","properties":{"period_start":{"type":"string","format":"date-time"},"period_end":{"type":"string","format":"date-time"},"active_learners":{"type":"integer"},"learner_count":{"type":"integer"},"package_count":{"type":"integer"},"launch_count":{"type":"integer"},"dispatch_count":{"type":"integer"},"currency":{"type":"string"},"estimated_cost_cents":{"type":"integer"},"included_learners":{"type":"integer"},"overage_learners":{"type":"integer"},"learner_overage_unit_cents":{"type":"integer"},"source":{"type":"string","enum":["allure_connect"]},"updated_at":{"type":"string","format":"date-time"},"scope":{"type":"object","properties":{"tenant_id":{"type":"string"},"user_id":{"type":"string","nullable":true},"learner_id":{"type":"string","nullable":true},"workspace_external_id":{"type":"string","nullable":true}}}}}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/upload":{"post":{"tags":["Packages"],"summary":"Direct multipart upload of a SCORM ZIP (small packages)","description":"Small-file compatibility route only: upload a `.zip` as `multipart/form-data`, below the hosting platform request-body limit (use under 4 MB). This route cannot bypass Vercel request-body limits. For larger files use `POST /api/v1/packages/upload-url` or `POST /api/v1/packages/multipart/init`, upload directly to storage, then call `POST /api/v1/packages/process`. Tenant is taken from the API key.","operationId":"directMultipartUploadPackage","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"SCORM package ZIP archive"},"uploaded_by":{"type":"string","description":"Uploader identifier (defaults to API key id if omitted)"}}}}}},"responses":{"200":{"description":"Archive accepted and staged for processing","content":{"application/json":{"schema":{"type":"object","required":["success","upload_id","storage_path","storage_backend","filename","file_size","uploaded_by"],"properties":{"success":{"type":"boolean","enum":[true]},"upload_id":{"type":"string","format":"uuid"},"storage_path":{"type":"string"},"storage_backend":{"type":"string","enum":["r2","disabled"]},"filename":{"type":"string"},"file_size":{"type":"number","minimum":0},"uploaded_by":{"type":"string"}}}}}},"400":{"description":"Missing file, invalid type, or validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"File exceeds the effective upload limit or cumulative storage quota","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","code","current_plan","max_upload_mb","limit_source","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["FILE_TOO_LARGE"]},"current_plan":{"type":"string"},"max_upload_mb":{"type":"number","description":"Effective ceiling: the lower of the deployment and current-plan limits."},"limit_source":{"type":"string","enum":["plan","platform"]},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_upload_mb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_upload_mb":{"type":"number"}},"additionalProperties":false}]}},"additionalProperties":false,"examples":{"currentPlatformCap":{"value":{"error":"File too large. This deployment currently supports uploads up to 500 MB. A plan upgrade will not increase this processing limit.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":500,"limit_source":"platform","suggested_plan":null}},"tierUpgradeWhenPlatformAllows":{"value":{"error":"File too large. Maximum upload size for your plan is 2048 MB. Growth supports uploads up to 5120 MB.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":2048,"limit_source":"plan","suggested_plan":{"tier":"professional","name":"Growth","max_upload_mb":5120}}}}},{"type":"object","required":["error","code","current_plan","max_storage_gb","current_storage_gb","projected_storage_gb","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["STORAGE_QUOTA_EXCEEDED"]},"current_plan":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0},"current_storage_gb":{"type":"number","minimum":0},"projected_storage_gb":{"type":"number","minimum":0},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_storage_gb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0}},"additionalProperties":false}]}},"additionalProperties":false}]}}}},"502":{"description":"Failed to store archive","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Storage or storage-quota state is temporarily unavailable; retry later","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/upload-url":{"post":{"tags":["Packages"],"summary":"Get presigned URL for direct upload","description":"Generate a presigned URL for direct client upload to Cloudflare R2 storage. This bypasses Vercel's body size limits and reduces egress costs.\n\n**Requirements:**\n- Cloudflare R2 must be configured\n- File must be a ZIP archive\n- The declared size may be up to 10 GB, but the effective limit is the lower of the deployment ceiling (currently 500 MB by default) and the tenant plan. A 413 response reports the effective limit and only suggests a plan when that plan can really fit the file.\n\n**Usage:**\n1. Call this endpoint to get presigned URL\n2. Upload file directly to R2 using presigned URL\n3. Call `/api/v1/packages/process` to process the uploaded file\n\n**Example:**\n```bash\ncurl -X POST https://app.allureconnect.com/api/v1/packages/upload-url \\\n  -H \"Authorization: Bearer your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"filename\": \"course.zip\",\n    \"file_size\": 52428800,\n    \"uploaded_by\": \"user-123\"\n  }'\n```\n\n**Alias:** `POST /api/v1/packages/upload-sessions` is identical to this endpoint.","operationId":"getUploadUrl","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["filename","file_size","uploaded_by"],"properties":{"tenant_id":{"type":"string","format":"uuid","description":"Tenant context (defaults to API key tenant)"},"filename":{"type":"string","description":"ZIP filename (must end with .zip)","example":"course.zip"},"file_size":{"type":"integer","minimum":1,"maximum":10737418240,"description":"Declared file size in bytes (schema max 10 GB; effective deployment/plan limit is enforced separately)"},"uploaded_by":{"type":"string","description":"Identifier of the user or system uploading"}}}}}},"responses":{"200":{"description":"Presigned URL generated","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["upload_id","storage_path","presigned_url","storage_type","bucket","max_upload_mb","presigned_expires_in_seconds","presigned_expires_at","upload_method","required_put_headers"],"properties":{"upload_id":{"type":"string","format":"uuid"},"storage_path":{"type":"string"},"presigned_url":{"type":"string","format":"uri","description":"Presigned S3 PUT URL for R2 (binds Content-Type and size when R2 is configured)"},"storage_type":{"type":"string","enum":["r2","disabled"]},"bucket":{"type":"string"},"max_upload_mb":{"type":"number"},"presigned_expires_in_seconds":{"type":"integer","description":"Lifetime of the presigned URL in seconds from mint time"},"presigned_expires_at":{"type":"string","format":"date-time","description":"ISO8601 expiration instant for the presigned URL"},"expires_at":{"type":"string","format":"date-time","description":"Same as presigned_expires_at (compat alias)"},"upload_method":{"type":"string","enum":["PUT"]},"required_put_headers":{"type":"object","required":["Content-Type"],"description":"Send these headers with the PUT; Content-Type is bound in the presigned signature","properties":{"Content-Type":{"type":"string","enum":["application/zip"]}},"additionalProperties":false}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"File exceeds the effective upload limit or cumulative storage quota","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","code","current_plan","max_upload_mb","limit_source","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["FILE_TOO_LARGE"]},"current_plan":{"type":"string"},"max_upload_mb":{"type":"number","description":"Effective ceiling: the lower of the deployment and current-plan limits."},"limit_source":{"type":"string","enum":["plan","platform"]},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_upload_mb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_upload_mb":{"type":"number"}},"additionalProperties":false}]}},"additionalProperties":false,"examples":{"currentPlatformCap":{"value":{"error":"File too large. This deployment currently supports uploads up to 500 MB. A plan upgrade will not increase this processing limit.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":500,"limit_source":"platform","suggested_plan":null}},"tierUpgradeWhenPlatformAllows":{"value":{"error":"File too large. Maximum upload size for your plan is 2048 MB. Growth supports uploads up to 5120 MB.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":2048,"limit_source":"plan","suggested_plan":{"tier":"professional","name":"Growth","max_upload_mb":5120}}}}},{"type":"object","required":["error","code","current_plan","max_storage_gb","current_storage_gb","projected_storage_gb","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["STORAGE_QUOTA_EXCEEDED"]},"current_plan":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0},"current_storage_gb":{"type":"number","minimum":0},"projected_storage_gb":{"type":"number","minimum":0},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_storage_gb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0}},"additionalProperties":false}]}},"additionalProperties":false}]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"502":{"description":"Presigned URL generation failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Storage or storage-quota state is temporarily unavailable; retry later","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/dispatches/{id}/retry":{"post":{"tags":["Dispatches"],"summary":"Retry the latest failed dispatch postback","description":"Retries the latest failed or dead-letter dispatch postback after tenant authorization. The operation is intended for an approved AllureLMS action or an internal/admin API key; it does not grant the language model direct mutation access.","operationId":"retryDispatchPostback","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Dispatch identifier"}],"responses":{"200":{"description":"Retry accepted and the current delivery result returned","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"accepted":{"type":"boolean","const":true},"delivery":{"type":"object","additionalProperties":true}}}}}}}},"401":{"description":"Missing or invalid service credential or API key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Dispatch postback delivery not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Latest delivery is not retryable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/intelligence/brief":{"post":{"tags":["Intelligence"],"summary":"Build an evidence-backed role brief","description":"Ranks typed facts deterministically, prepares allowlisted actions that always require approval, and optionally enhances the language through the OpenAI API. Provider failure returns deterministic language.","operationId":"createIntelligenceBrief","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tenantId","actorId","actorRole","surface","facts","maximumActions"],"additionalProperties":false,"properties":{"tenantId":{"type":"string","maxLength":200},"actorId":{"type":"string","maxLength":200},"actorRole":{"type":"string","enum":["learner","teacher","manager","builder","admin"]},"surface":{"type":"string","enum":["learner_home","teacher_pulse","manager_home","builder_launchpad","admin_command"]},"facts":{"type":"array","maxItems":1000,"items":{"type":"object","additionalProperties":true}},"maximumActions":{"type":"integer","minimum":0,"maximum":10}}}}}},"responses":{"200":{"description":"Schema-valid deterministic or AI-assisted brief","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid typed intelligence request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Missing or invalid service credential or API key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/intelligence/extract":{"post":{"tags":["Intelligence"],"summary":"Extract structured skills for human review","description":"Starts schema-validated skill extraction for an authorized Builder or Admin. Extracted mappings retain evidence and require the normal review/approval flow.","operationId":"extractIntelligenceSkills","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tenantId","actorId","actorRole"],"additionalProperties":false,"properties":{"tenantId":{"type":"string","maxLength":200},"actorId":{"type":"string","maxLength":200},"actorRole":{"type":"string","enum":["builder","admin"]},"packageId":{"type":"string","maxLength":200},"packageVersion":{"type":"string","maxLength":200}}}}}},"responses":{"202":{"description":"Extraction accepted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid extraction request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Missing or invalid service credential or API key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"Required Graph tier is unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Tenant mismatch or authorization failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/intelligence/feedback":{"post":{"tags":["Intelligence"],"summary":"Record an intelligence decision signal","description":"Records approve, edit, defer, dismiss, incorrect-evidence, or undo feedback for audit and evaluation. Feedback never trains a model automatically.","operationId":"recordIntelligenceFeedback","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tenantId","actorId","actorRole","briefId","event","occurredAt"],"additionalProperties":false,"properties":{"tenantId":{"type":"string","maxLength":200},"actorId":{"type":"string","maxLength":200},"actorRole":{"type":"string","enum":["learner","teacher","manager","builder","admin"]},"briefId":{"type":"string","maxLength":200},"proposalId":{"type":"string","maxLength":200},"event":{"type":"string","enum":["approve","edit","defer","dismiss","incorrect_evidence","undo"]},"reasonCode":{"type":"string","maxLength":100},"note":{"type":"string","maxLength":1000},"occurredAt":{"type":"string","format":"date-time"}}}}}},"responses":{"202":{"description":"Feedback recorded","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid feedback event","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Missing or invalid service credential or API key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/multipart/init":{"post":{"tags":["Packages"],"summary":"Initialize a resumable multipart upload","description":"JSON preflight and R2 multipart initialization for large SCORM ZIPs. The declared size is checked against the effective platform/plan ceiling before any multipart session is created.","operationId":"initializeMultipartPackageUpload","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["filename","file_size"],"properties":{"filename":{"type":"string","pattern":"\\.[zZ][iI][pP]$","example":"large-course.zip"},"file_size":{"type":"integer","minimum":1,"example":262144000},"uploaded_by":{"type":"string","description":"Defaults to the API key id."}}}}}},"responses":{"200":{"description":"Multipart upload initialized","content":{"application/json":{"schema":{"type":"object","required":["upload_id","multipart_upload_id","storage_path","part_size_bytes","max_upload_mb","part_count"],"properties":{"upload_id":{"type":"string"},"multipart_upload_id":{"type":"string"},"storage_path":{"type":"string"},"part_size_bytes":{"type":"integer"},"max_upload_mb":{"type":"number"},"part_count":{"type":"integer"}}}}}},"400":{"description":"Invalid multipart preflight request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"File exceeds the effective upload limit or cumulative storage quota","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","code","current_plan","max_upload_mb","limit_source","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["FILE_TOO_LARGE"]},"current_plan":{"type":"string"},"max_upload_mb":{"type":"number","description":"Effective ceiling: the lower of the deployment and current-plan limits."},"limit_source":{"type":"string","enum":["plan","platform"]},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_upload_mb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_upload_mb":{"type":"number"}},"additionalProperties":false}]}},"additionalProperties":false,"examples":{"currentPlatformCap":{"value":{"error":"File too large. This deployment currently supports uploads up to 500 MB. A plan upgrade will not increase this processing limit.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":500,"limit_source":"platform","suggested_plan":null}},"tierUpgradeWhenPlatformAllows":{"value":{"error":"File too large. Maximum upload size for your plan is 2048 MB. Growth supports uploads up to 5120 MB.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":2048,"limit_source":"plan","suggested_plan":{"tier":"professional","name":"Growth","max_upload_mb":5120}}}}},{"type":"object","required":["error","code","current_plan","max_storage_gb","current_storage_gb","projected_storage_gb","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["STORAGE_QUOTA_EXCEEDED"]},"current_plan":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0},"current_storage_gb":{"type":"number","minimum":0},"projected_storage_gb":{"type":"number","minimum":0},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_storage_gb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0}},"additionalProperties":false}]}},"additionalProperties":false}]}}}},"503":{"description":"Storage or storage-quota state is temporarily unavailable; retry later","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/vr/uploads/preflight":{"post":{"tags":["Packages"],"summary":"Preflight a VR APK upload size","description":"API-key-authenticated JSON size check for VR artifacts. It creates no R2 object or upload session. The multipart/form-data VR upload route remains small-body-only; use this endpoint before attempting it.","operationId":"preflightVrUpload","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["file_size"],"properties":{"file_size":{"type":"integer","minimum":1}},"additionalProperties":false}}}},"responses":{"200":{"description":"Declared size is allowed","content":{"application/json":{"schema":{"type":"object","required":["allowed","max_upload_mb"],"properties":{"allowed":{"type":"boolean","enum":[true]},"max_upload_mb":{"type":"number"}}}}}},"400":{"description":"Invalid preflight request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"File exceeds the effective upload limit or cumulative storage quota","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","code","current_plan","max_upload_mb","limit_source","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["FILE_TOO_LARGE"]},"current_plan":{"type":"string"},"max_upload_mb":{"type":"number","description":"Effective ceiling: the lower of the deployment and current-plan limits."},"limit_source":{"type":"string","enum":["plan","platform"]},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_upload_mb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_upload_mb":{"type":"number"}},"additionalProperties":false}]}},"additionalProperties":false,"examples":{"currentPlatformCap":{"value":{"error":"File too large. This deployment currently supports uploads up to 500 MB. A plan upgrade will not increase this processing limit.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":500,"limit_source":"platform","suggested_plan":null}},"tierUpgradeWhenPlatformAllows":{"value":{"error":"File too large. Maximum upload size for your plan is 2048 MB. Growth supports uploads up to 5120 MB.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":2048,"limit_source":"plan","suggested_plan":{"tier":"professional","name":"Growth","max_upload_mb":5120}}}}},{"type":"object","required":["error","code","current_plan","max_storage_gb","current_storage_gb","projected_storage_gb","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["STORAGE_QUOTA_EXCEEDED"]},"current_plan":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0},"current_storage_gb":{"type":"number","minimum":0},"projected_storage_gb":{"type":"number","minimum":0},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_storage_gb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0}},"additionalProperties":false}]}},"additionalProperties":false}]}}}},"503":{"description":"Storage or storage-quota state is temporarily unavailable; retry later","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/vr/uploads":{"post":{"tags":["Packages"],"summary":"Direct upload of a small VR APK artifact","description":"Small-file multipart/form-data compatibility route (use under 4 MB). `POST /api/v1/vr/uploads/preflight` checks the declared size without transferring bytes, but it does not create a large-file transport: this direct route still cannot bypass Vercel request-body limits. A dedicated presigned VR artifact upload flow is not currently available.","operationId":"directUploadVrArtifact","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"APK artifact"},"uploaded_by":{"type":"string"}}}}}},"responses":{"200":{"description":"VR artifact accepted and staged"},"400":{"description":"Missing or invalid APK artifact","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"File exceeds the effective upload limit or cumulative storage quota","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","code","current_plan","max_upload_mb","limit_source","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["FILE_TOO_LARGE"]},"current_plan":{"type":"string"},"max_upload_mb":{"type":"number","description":"Effective ceiling: the lower of the deployment and current-plan limits."},"limit_source":{"type":"string","enum":["plan","platform"]},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_upload_mb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_upload_mb":{"type":"number"}},"additionalProperties":false}]}},"additionalProperties":false,"examples":{"currentPlatformCap":{"value":{"error":"File too large. This deployment currently supports uploads up to 500 MB. A plan upgrade will not increase this processing limit.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":500,"limit_source":"platform","suggested_plan":null}},"tierUpgradeWhenPlatformAllows":{"value":{"error":"File too large. Maximum upload size for your plan is 2048 MB. Growth supports uploads up to 5120 MB.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":2048,"limit_source":"plan","suggested_plan":{"tier":"professional","name":"Growth","max_upload_mb":5120}}}}},{"type":"object","required":["error","code","current_plan","max_storage_gb","current_storage_gb","projected_storage_gb","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["STORAGE_QUOTA_EXCEEDED"]},"current_plan":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0},"current_storage_gb":{"type":"number","minimum":0},"projected_storage_gb":{"type":"number","minimum":0},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_storage_gb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0}},"additionalProperties":false}]}},"additionalProperties":false}]}}}},"503":{"description":"Storage or storage-quota state is temporarily unavailable; retry later","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/scorm/packages":{"post":{"tags":["Packages"],"summary":"Legacy small-file SCORM upload compatibility route","description":"Legacy multipart/form-data upload-and-process route, subject to the hosting platform request-body limit. API clients should use upload-url or multipart init for files above the small-body limit.","operationId":"legacyDirectScormUpload","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"SCORM ZIP archive"},"title":{"type":"string","description":"Optional package title"},"uploaded_by":{"type":"string","description":"Optional uploader reference"}}}}}},"responses":{"201":{"description":"SCORM package uploaded and processed"},"400":{"description":"Missing or invalid ZIP archive","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"File exceeds the effective upload limit or cumulative storage quota","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","code","current_plan","max_upload_mb","limit_source","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["FILE_TOO_LARGE"]},"current_plan":{"type":"string"},"max_upload_mb":{"type":"number","description":"Effective ceiling: the lower of the deployment and current-plan limits."},"limit_source":{"type":"string","enum":["plan","platform"]},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_upload_mb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_upload_mb":{"type":"number"}},"additionalProperties":false}]}},"additionalProperties":false,"examples":{"currentPlatformCap":{"value":{"error":"File too large. This deployment currently supports uploads up to 500 MB. A plan upgrade will not increase this processing limit.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":500,"limit_source":"platform","suggested_plan":null}},"tierUpgradeWhenPlatformAllows":{"value":{"error":"File too large. Maximum upload size for your plan is 2048 MB. Growth supports uploads up to 5120 MB.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":2048,"limit_source":"plan","suggested_plan":{"tier":"professional","name":"Growth","max_upload_mb":5120}}}}},{"type":"object","required":["error","code","current_plan","max_storage_gb","current_storage_gb","projected_storage_gb","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["STORAGE_QUOTA_EXCEEDED"]},"current_plan":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0},"current_storage_gb":{"type":"number","minimum":0},"projected_storage_gb":{"type":"number","minimum":0},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_storage_gb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0}},"additionalProperties":false}]}},"additionalProperties":false}]}}}},"503":{"description":"Storage or storage-quota state is temporarily unavailable; retry later","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/upload-sessions":{"post":{"tags":["Packages"],"summary":"Get presigned URL for direct upload","description":"Generate a presigned URL for direct client upload to Cloudflare R2 storage. This bypasses Vercel's body size limits and reduces egress costs.\n\n**Requirements:**\n- Cloudflare R2 must be configured\n- File must be a ZIP archive\n- The declared size may be up to 10 GB, but the effective limit is the lower of the deployment ceiling (currently 500 MB by default) and the tenant plan. A 413 response reports the effective limit and only suggests a plan when that plan can really fit the file.\n\n**Usage:**\n1. Call this endpoint to get presigned URL\n2. Upload file directly to R2 using presigned URL\n3. Call `/api/v1/packages/process` to process the uploaded file\n\n**Example:**\n```bash\ncurl -X POST https://app.allureconnect.com/api/v1/packages/upload-url \\\n  -H \"Authorization: Bearer your-api-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"filename\": \"course.zip\",\n    \"file_size\": 52428800,\n    \"uploaded_by\": \"user-123\"\n  }'\n```\n\n**Alias:** `POST /api/v1/packages/upload-sessions` is identical to this endpoint.","operationId":"getUploadUrl","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["filename","file_size","uploaded_by"],"properties":{"tenant_id":{"type":"string","format":"uuid","description":"Tenant context (defaults to API key tenant)"},"filename":{"type":"string","description":"ZIP filename (must end with .zip)","example":"course.zip"},"file_size":{"type":"integer","minimum":1,"maximum":10737418240,"description":"Declared file size in bytes (schema max 10 GB; effective deployment/plan limit is enforced separately)"},"uploaded_by":{"type":"string","description":"Identifier of the user or system uploading"}}}}}},"responses":{"200":{"description":"Presigned URL generated","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","required":["upload_id","storage_path","presigned_url","storage_type","bucket","max_upload_mb","presigned_expires_in_seconds","presigned_expires_at","upload_method","required_put_headers"],"properties":{"upload_id":{"type":"string","format":"uuid"},"storage_path":{"type":"string"},"presigned_url":{"type":"string","format":"uri","description":"Presigned S3 PUT URL for R2 (binds Content-Type and size when R2 is configured)"},"storage_type":{"type":"string","enum":["r2","disabled"]},"bucket":{"type":"string"},"max_upload_mb":{"type":"number"},"presigned_expires_in_seconds":{"type":"integer","description":"Lifetime of the presigned URL in seconds from mint time"},"presigned_expires_at":{"type":"string","format":"date-time","description":"ISO8601 expiration instant for the presigned URL"},"expires_at":{"type":"string","format":"date-time","description":"Same as presigned_expires_at (compat alias)"},"upload_method":{"type":"string","enum":["PUT"]},"required_put_headers":{"type":"object","required":["Content-Type"],"description":"Send these headers with the PUT; Content-Type is bound in the presigned signature","properties":{"Content-Type":{"type":"string","enum":["application/zip"]}},"additionalProperties":false}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"File exceeds the effective upload limit or cumulative storage quota","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","code","current_plan","max_upload_mb","limit_source","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["FILE_TOO_LARGE"]},"current_plan":{"type":"string"},"max_upload_mb":{"type":"number","description":"Effective ceiling: the lower of the deployment and current-plan limits."},"limit_source":{"type":"string","enum":["plan","platform"]},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_upload_mb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_upload_mb":{"type":"number"}},"additionalProperties":false}]}},"additionalProperties":false,"examples":{"currentPlatformCap":{"value":{"error":"File too large. This deployment currently supports uploads up to 500 MB. A plan upgrade will not increase this processing limit.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":500,"limit_source":"platform","suggested_plan":null}},"tierUpgradeWhenPlatformAllows":{"value":{"error":"File too large. Maximum upload size for your plan is 2048 MB. Growth supports uploads up to 5120 MB.","code":"FILE_TOO_LARGE","current_plan":"starter","max_upload_mb":2048,"limit_source":"plan","suggested_plan":{"tier":"professional","name":"Growth","max_upload_mb":5120}}}}},{"type":"object","required":["error","code","current_plan","max_storage_gb","current_storage_gb","projected_storage_gb","suggested_plan"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["STORAGE_QUOTA_EXCEEDED"]},"current_plan":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0},"current_storage_gb":{"type":"number","minimum":0},"projected_storage_gb":{"type":"number","minimum":0},"suggested_plan":{"anyOf":[{"type":"null"},{"type":"object","required":["tier","name","max_storage_gb"],"properties":{"tier":{"type":"string","enum":["starter","professional","business"]},"name":{"type":"string"},"max_storage_gb":{"type":"number","minimum":0}},"additionalProperties":false}]}},"additionalProperties":false}]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"502":{"description":"Presigned URL generation failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Storage or storage-quota state is temporarily unavailable; retry later","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/upload-limit":{"get":{"tags":["Uploads"],"summary":"Get upload limit","description":"Returns the effective upload size ceiling for this environment. No authentication required.","operationId":"getUploadLimit","security":[],"responses":{"200":{"description":"Upload limit","content":{"application/json":{"schema":{"type":"object","required":["max_upload_mb","storage_type","r2_enabled"],"properties":{"max_upload_mb":{"type":"number","description":"Maximum file size in megabytes"},"storage_type":{"type":"string","enum":["r2","disabled"]},"r2_enabled":{"type":"boolean"}}}}}}}}},"/api/v1/packages/process":{"post":{"tags":["Uploads"],"summary":"Process an uploaded package","description":"Validates and extracts a SCORM/VR ZIP that was previously stored at `storage_path` (returned by the upload-url or multipart flow). Rate-limited per tenant: 60 req/60 s. Returns `X-RateLimit-*` headers on every response. Send `X-TrainingOS-Skill-Indexing-Consent: opted-out` when the creator opted out of skill indexing: the package is stored and delivered as usual but never indexed into the skill graph.","operationId":"processPackage","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"X-TrainingOS-Skill-Indexing-Consent","in":"header","required":false,"description":"Per-upload skill-indexing consent. `opted-out` skips skill-graph indexing for this package; `opted-in` or no header keeps the default.","schema":{"type":"string","enum":["opted-in","opted-out"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["storage_path","original_filename"],"properties":{"storage_path":{"type":"string","description":"Storage path returned by the upload-url or multipart flow."},"original_filename":{"type":"string","description":"Original filename of the uploaded ZIP (used for display and error messages)."},"package_id":{"type":"string","pattern":"^[A-Za-z0-9_-]+$","maxLength":512,"description":"Desired package_id slug. Auto-generated when omitted."},"connector_installation_id":{"type":"string","format":"uuid"},"acquisition_source":{"type":"string","enum":["wordpress_org","github","in_app","partner"]},"validate_only":{"type":"boolean","description":"When true, validate without persisting a package record."},"tenant_id":{"type":"string","description":"Ignored — the API key tenant is used. Accepted for client compatibility only."},"uploaded_by":{"type":"string","description":"Ignored — set to the API key id by the route. Accepted for client compatibility only."}}}}}},"responses":{"200":{"description":"Package processed successfully","content":{"application/json":{"schema":{"type":"object","required":["upload_id","manifest","file_size_bytes","storage_path"],"properties":{"upload_id":{"type":"string"},"validation_only":{"type":"boolean"},"manifest":{"type":"object","required":["title","version","launch_url","sco_count","description","duration"],"properties":{"title":{"type":"string"},"version":{"type":"string","enum":["1.2","2004"]},"launch_url":{"type":"string"},"sco_count":{"type":"integer","minimum":0},"activities":{"type":"array","items":{"type":"object","required":["id","title"],"properties":{"id":{"type":"string"},"title":{"type":"string"}}}},"description":{"type":"string"},"duration":{"type":"string"}}},"file_size_bytes":{"type":"number","minimum":0},"storage_path":{"type":"string"},"package":{"type":"object","required":["package_id","title","launch_url","version","current_revision"],"properties":{"package_id":{"type":"string"},"title":{"type":"string"},"launch_url":{"type":"string"},"version":{"type":"string","enum":["1.2","2004"]},"current_revision":{"type":"integer","minimum":1}}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PACKAGE_LIMIT_REACHED: the Free plan includes 3 packages (archive one or upgrade)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"File exceeds upload or storage quota limit","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Storage temporarily unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/multipart/part-url":{"post":{"tags":["Uploads"],"summary":"Get a presigned URL for one multipart part","description":"Returns a short-lived presigned PUT URL for a single part of an in-progress multipart upload (initiated via `POST /api/v1/packages/multipart/init`). `part_number` is 1-indexed, max 10 000.","operationId":"getMultipartPartUrl","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["upload_id","part_number"],"properties":{"upload_id":{"type":"string"},"part_number":{"type":"integer","minimum":1,"maximum":10000}}}}}},"responses":{"200":{"description":"Part URL","content":{"application/json":{"schema":{"type":"object","required":["url","expires_in","content_length_bytes"],"properties":{"url":{"type":"string","format":"uri"},"expires_in":{"type":"number","description":"Seconds until the URL expires"},"content_length_bytes":{"type":"integer"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Multipart upload not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/multipart/complete":{"post":{"tags":["Uploads"],"summary":"Complete a multipart upload","description":"Finalises a multipart upload by supplying the ordered list of ETags returned by S3/R2 for each part PUT. The assembled object is then ready to pass to `POST /api/v1/packages/process`.","operationId":"completeMultipartUpload","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["upload_id","parts"],"properties":{"upload_id":{"type":"string"},"parts":{"type":"array","minItems":1,"items":{"type":"object","required":["part_number","etag"],"properties":{"part_number":{"type":"integer","minimum":1,"maximum":10000},"etag":{"type":"string"}}}}}}}}},"responses":{"200":{"description":"Multipart upload completed","content":{"application/json":{"schema":{"type":"object","required":["upload_id","storage_path","tenant_id","uploaded_by","filename","next_step"],"properties":{"upload_id":{"type":"string"},"storage_path":{"type":"string"},"tenant_id":{"type":"string"},"uploaded_by":{"type":"string"},"filename":{"type":"string"},"next_step":{"type":"string"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Multipart upload not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"502":{"description":"Remote storage assembly failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/multipart/abort":{"post":{"tags":["Uploads"],"summary":"Abort a multipart upload","description":"Cancels an in-progress multipart upload and frees any staged parts. Idempotent: calling again on an already-aborted or completed upload returns `already_aborted` / `already_completed` without error.","operationId":"abortMultipartUpload","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["upload_id"],"properties":{"upload_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Abort result","content":{"application/json":{"schema":{"type":"object","required":["upload_id","storage_path","status","aborted"],"properties":{"upload_id":{"type":"string"},"storage_path":{"type":"string"},"status":{"type":"string","enum":["aborted","already_aborted","already_completed"]},"aborted":{"type":"boolean"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Multipart upload not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"502":{"description":"Storage abort failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/upload-progress/{uploadId}":{"get":{"tags":["Uploads"],"summary":"Get upload processing progress","description":"Poll after `POST /api/v1/packages/process` to track progress through extraction, validation, and persistence stages.","operationId":"getUploadProgress","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"uploadId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Upload progress","content":{"application/json":{"schema":{"type":"object","required":["upload_id","status","stage","uploaded_bytes","total_bytes","percent_complete","error","metadata","updated_at"],"properties":{"upload_id":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","failed"]},"stage":{"type":"string","enum":["uploading","uploaded","validating","extracting","persisting","completed","failed"]},"uploaded_bytes":{"type":"integer"},"total_bytes":{"type":"integer"},"percent_complete":{"type":"number","minimum":0,"maximum":100},"error":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":true},"updated_at":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Upload not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/{packageId}/versions":{"get":{"tags":["Packages"],"summary":"List package versions","description":"Returns the version history for a package.","operationId":"listPackageVersions","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Package versions","content":{"application/json":{"schema":{"type":"object","required":["versions"],"properties":{"versions":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/dispatches/launch":{"post":{"tags":["Dispatches"],"summary":"Launch a dispatch (learner-facing)","description":"Unauthenticated endpoint called by the LMS-embedded SCORM package to obtain a session launch URL. Requires a signed dispatch `token` (JWT signed with `CONNECT_DISPATCH_TOKEN_SECRET`). If the dispatch has `allowed_domains`, the `Origin` or `Referer` header must match. Optional `access_password` is required when the dispatch has a password gate.","operationId":"launchDispatch","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"Signed dispatch JWT"},"user_id":{"type":"string","description":"Learner identifier (required when not embedded in token)"},"external_registration_id":{"type":"string","description":"Opaque LMS registration ID"},"access_password":{"type":"string","description":"Plaintext access password if the dispatch is gated"}}}}}},"responses":{"200":{"description":"Launch payload (session URL + metadata)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"ACTIVE_LEARNER_CAP_REACHED: the workspace reached its Free active-learner cap, or its TEST-mode allowance","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Invalid / expired token, origin not allowed, or wrong password","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/launch-links/validate":{"get":{"tags":["Dispatches"],"summary":"Validate a launch link (GET)","description":"Self-service health check for a launch URL. Supply the URL as `?url=` query parameter. Unauthenticated and read-only. Reports whether the URL points at a valid player surface, whether it carries a token, and whether the token is valid / expired / malformed.","operationId":"validateLaunchLinkGet","security":[],"parameters":[{"name":"url","in":"query","required":false,"schema":{"type":"string","format":"uri"},"description":"The launch URL to validate"}],"responses":{"200":{"description":"Validation result","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"has_token":{"type":"boolean"},"token_status":{"type":"string","enum":["valid","expired","malformed","absent"]},"issues":{"type":"array","items":{"type":"string"}}}}}}}}},"post":{"tags":["Dispatches"],"summary":"Validate a launch link (POST)","description":"Same as GET variant but accepts `{ \"url\": \"...\" }` in a JSON body instead of a query parameter.","operationId":"validateLaunchLinkPost","security":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Validation result","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"has_token":{"type":"boolean"},"token_status":{"type":"string","enum":["valid","expired","malformed","absent"]},"issues":{"type":"array","items":{"type":"string"}}}}}}}}}},"/api/v1/create/hosted-conversions":{"post":{"tags":["Create"],"summary":"Activate a Connect-hosted conversion (v1)","description":"Creates or replays a Connect-hosted metered delivery for an Allure Create package version (2026-07-15 contract). Requires `internal_product` or `admin` scope and a valid `Idempotency-Key` header. Gated on `CONNECT_CREATE_HOSTED_CONVERSION_ENABLED`. Returns 503 `CREATE_HOSTED_CONVERSION_DISABLED` when the feature flag is off.","operationId":"activateCreateHostedConversionV1","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"createHostedConversionRequestSchema payload (see lib/contracts/connect-create-publish.ts)"}}}},"responses":{"200":{"description":"Conversion replayed (idempotent)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"201":{"description":"Conversion activated","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request or missing Idempotency-Key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Insufficient scope or portfolio proof failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Feature disabled or storage unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/create/hosted-conversions/deactivate":{"post":{"tags":["Create"],"summary":"Deactivate a Connect-hosted conversion (v1)","description":"Stops metering for a previously activated hosted conversion. Remains callable even when the feature flag is off so rollback does not trap an active customer meter. Idempotent.","operationId":"deactivateCreateHostedConversionV1","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"createHostedDeactivationRequestSchema payload"}}}},"responses":{"200":{"description":"Deactivation result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request or missing Idempotency-Key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/create/publishes/query":{"post":{"tags":["Create"],"summary":"Query a Create publish record (v1)","description":"Looks up an existing Create publish receipt by portfolio proof. Returns 404 when not found. Used by Allure Create to replay a completed packaging result without re-running the full flow.","operationId":"queryCreatePublishV1","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["portfolio"],"properties":{"portfolio":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Publish record","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Create publish not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/create/publishes/recover":{"post":{"tags":["Create"],"summary":"Recover / reconcile a stale Create packaging receipt (v1)","description":"Reconciles a packaging receipt whose outcome is uncertain (e.g. server crash between reservation and packaging claim). Returns 202 while still `packaging` or `reconciling`.","operationId":"recoverCreatePublishV1","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"createPublishRecoveryRequestSchema payload"}}}},"responses":{"200":{"description":"Recovery result (terminal outcome)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"202":{"description":"Recovery in progress","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid recovery request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/create/workspace-links":{"post":{"tags":["Create"],"summary":"Register or revoke a Create workspace link (v1)","description":"Registry-confirmed provisioning / revocation surface. `admin` scope only. Pass `status: \"active\"` with a portfolio proof to record a verified link; pass `status: \"revoked\"` to stop all active meters, revoke billing eligibility, and write audit evidence.","operationId":"upsertCreateWorkspaceLinkV1","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["portfolio","status"],"properties":{"status":{"type":"string","enum":["active"]},"portfolio":{"type":"object","additionalProperties":true}}},{"type":"object","required":["status","productWorkspaceLinkId","allureAccountId","allureWorkspaceId"],"properties":{"status":{"type":"string","enum":["revoked"]},"productWorkspaceLinkId":{"type":"string"},"allureAccountId":{"type":"string"},"allureWorkspaceId":{"type":"string"}}}]}}}},"responses":{"200":{"description":"Link revoked","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"201":{"description":"Link registered","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Insufficient scope (admin required) or proof failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Workspace link not found (revoke path)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/create/artifacts/download":{"post":{"tags":["Create"],"summary":"Download a Create SCORM artifact (v1)","description":"Streams the binary SCORM ZIP for a completed Create production-download publish. Requires a fresh portfolio proof; the artifact must match the exact receipt, package, and version. Returns `Content-Disposition: attachment` with the original filename.","operationId":"downloadCreateArtifactV1","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["portfolio","artifact_id"],"properties":{"portfolio":{"type":"object","additionalProperties":true},"artifact_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Binary SCORM ZIP","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Create publish or artifact not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Artifact temporarily unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v2/connect-packages":{"post":{"tags":["Create"],"summary":"Package one immutable learner manifest (v2)","description":"Creates a Connect SCORM package from an Allure Create immutable learner manifest (contract `2026-07-17`, operation `createConnectPackageV2`). Body is the strict Create-owned publish payload. Portfolio proof travels in `X-Allure-Portfolio-Proof`; the authorizing workspace link in `X-Allure-Product-Workspace-Link`. **App host only** — not routed on `api.allureconnect.com`. New acceptance remains inactive until the default-off receiver flag is true and the exact tenant/workspace pair is in the server-side allowlist. Missing or invalid configuration fails closed; protected customer tenant identities return `503 CREATE_PUBLISH_V2_DISABLED` before proof, workspace-link, or ledger access.","operationId":"createConnectPackageV2","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Allure-Portfolio-Proof","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Allure-Product-Workspace-Link","in":"header","required":false,"description":"Required for new acceptance unless the strict destination body already carries the same productWorkspaceLinkId. Existing receipt replay may omit it only when the stored/request identity is otherwise complete.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"description":"Allure Create 2026-07-17 strict publish body (see lib/contracts/connect-create-publish-v2.ts)"}}}},"responses":{"200":{"description":"Receipt (idempotent replay)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"202":{"description":"New publish accepted; poll /api/v2/connect-packages/by-idempotency/{idempotencyKey} until terminal","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Portfolio proof failed or insufficient scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Idempotency, receipt, or destination conflict","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"Manifest or publish provenance rejected","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Packaging capacity or rate limit reached","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Feature disabled","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v2/connect-packages/by-idempotency/{idempotencyKey}":{"get":{"tags":["Create"],"summary":"Reconcile a v2 package by idempotency key","description":"Reads the existing receipt for a known idempotency key before deciding whether to retry a lost response. Returns 202 when outcome is still unknown. Intentionally not gated by the `CONNECT_CREATE_PUBLISH_V2_ENABLED` flag or the new-acceptance allowlist so disabling new acceptance never strands an existing receipt. An unknown or reconciling receipt is not a terminal downstream handoff. The server-side protected-workspace denial is stronger than rollback continuity and returns `503 CREATE_PUBLISH_V2_DISABLED` before proof or ledger access.","operationId":"reconcileConnectPackageV2","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"idempotencyKey","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Allure-Portfolio-Proof","in":"header","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Receipt (current non-reconciling state; inspect the body for terminality)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"202":{"description":"Outcome still unknown","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Portfolio proof header required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Receipt not found or proof cannot read it","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Authenticated receipt reconstruction mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Portfolio proof keys temporarily unavailable or protected workspace disabled","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v2/connect-packages/hosted-conversions":{"post":{"tags":["Create"],"summary":"Complete Connect-hosted stage for a v2 package","description":"Activates the Connect-owned persistent-hosting meter for one exact v2 package version. Body is `plans.connectHosted.payload` from the adapter fixtures. New conversion binding requires the same default-off receiver flag and exact server-side tenant/workspace allowlist eligibility as package acceptance. Existing active bindings remain replayable after disablement. A stage whose exact idempotency key was already durably bound may finish activation and start its one meter after disablement; the protected Furness denial still overrides that lifecycle before proof, workspace-link, or ledger access with `503 CREATE_PUBLISH_V2_DISABLED`. Metering starts here and nowhere else for v2 paths.","operationId":"convertConnectHostedV2","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Allure-Portfolio-Proof","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"plans.connectHosted.payload from destination-adapters-v2"}}}},"responses":{"200":{"description":"Receipt (replayed)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"202":{"description":"New hosted conversion accepted","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Portfolio proof failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Hosted binding or destination conflict","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"Invalid hosted request, destination, or workspace-link identity","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Feature disabled or workspace not eligible","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v2/connect-packages/artifacts/download":{"post":{"tags":["Create"],"summary":"Download a v2 production-download artifact","description":"Streams the SCORM ZIP for a completed `2026-07-17` production-download publish. Portfolio proof required; artifact must match the exact receipt. All \"you cannot have this artifact\" outcomes collapse to `CREATE_PUBLISH_NOT_FOUND` to avoid information leakage.","operationId":"downloadCreateArtifactV2","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"X-Allure-Portfolio-Proof","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["idempotency_key","artifact_id"],"properties":{"idempotency_key":{"type":"string"},"artifact_id":{"type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Binary SCORM ZIP","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Proof required or invalid","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"No completed production-download artifact matches this request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Artifact temporarily unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/conversions":{"post":{"tags":["Conversions"],"summary":"Submit a PPTX for SCORM conversion","description":"Accepts `multipart/form-data` with `file` (a `.pptx` binary), optional `scorm_version` (`\"1.2\"` or `\"2004\"`, default `\"2004\"`), `title` override, and `auto_publish` flag. Subject to monthly sandbox conversion limits. Returns 201 on success.","operationId":"createConversionJob","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":".pptx file"},"scorm_version":{"type":"string","enum":["1.2","2004"],"default":"2004"},"title":{"type":"string"},"auto_publish":{"type":"string","enum":["true","false"],"default":"true"}}}}}},"responses":{"201":{"description":"Conversion completed and package persisted","content":{"application/json":{"schema":{"type":"object","properties":{"job_id":{"type":"string"},"status":{"type":"string","enum":["completed","failed"]},"slide_count":{"type":"integer"},"title":{"type":"string"},"package_id":{"type":"string"},"launch_url":{"type":"string","format":"uri"},"persisted":{"type":"boolean"}}}}}},"400":{"description":"Invalid request or missing file","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"PPTX parse failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Monthly conversion limit reached","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Storage not configured","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"get":{"tags":["Conversions"],"summary":"List conversion jobs","description":"Returns all PPTX-to-SCORM conversion jobs for the authenticated tenant.","operationId":"listConversionJobs","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Conversion job list","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/conversions/{jobId}":{"get":{"tags":["Conversions"],"summary":"Get a conversion job","description":"Returns the status and result of a single PPTX conversion job.","operationId":"getConversionJob","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Conversion job","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Conversion job not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/quick-publish":{"post":{"tags":["Conversions"],"summary":"Quick-publish structured slides to a hosted SCORM package","description":"AI-optimised endpoint (\"Resend for SCORM\"): accepts structured slide content in JSON and returns a hosted SCORM package. No file upload required. Subject to sandbox monthly limits unless accompanied by a Create portfolio. Returns 201 on success; 202 when a Create-funded packaging is already in progress.","operationId":"quickPublish","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","slides"],"properties":{"title":{"type":"string","maxLength":200},"slides":{"type":"array","minItems":1,"items":{"type":"object","required":["title","content"],"properties":{"title":{"type":"string"},"content":{"type":"string"},"image_url":{"type":"string","format":"uri"}}}},"scorm_version":{"type":"string","enum":["1.2","2004"],"default":"2004"},"portfolio":{"type":"object","additionalProperties":true,"description":"Allure Create portfolio proof envelope (optional; enables Create-funded publish)"},"source":{"type":"string","description":"Source product (optional)"},"mode":{"type":"string","description":"Publish mode (optional, used with portfolio)"}}}}}},"responses":{"201":{"description":"Package created","content":{"application/json":{"schema":{"type":"object","properties":{"package_id":{"type":"string"},"package_version_id":{"type":"string"},"title":{"type":"string"},"scorm_version":{"type":"string"},"slide_count":{"type":"integer"},"sandbox":{"type":"boolean"},"persisted":{"type":"boolean"},"launch_url":{"type":"string","format":"uri","nullable":true},"total_size_bytes":{"type":"integer"},"file_count":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"create_publish":{"type":"object","additionalProperties":true}}}}}},"202":{"description":"Create packaging in progress","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Prior Create packaging attempt failed — use a new idempotency key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Storage not configured or Create publishing disabled","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/connectors/installations":{"get":{"tags":["Connectors"],"summary":"List connector installations","description":"Returns all registered connector installations for the authenticated tenant.","operationId":"listConnectorInstallations","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Connector installations","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Connectors"],"summary":"Register or update a connector installation","description":"Upserts a connector installation record (e.g. WordPress plugin). Rate-limited per tenant/key. For WordPress connectors, a short-lived referral token is returned and a funnel event is recorded.","operationId":"upsertConnectorInstallation","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["connectorId"],"properties":{"connectorId":{"type":"string","minLength":2},"externalInstallationId":{"type":"string","format":"uuid"},"acquisitionSource":{"type":"string","description":"Acquisition channel"},"siteUrl":{"type":"string","maxLength":500},"lmsType":{"type":"string","maxLength":32},"pluginVersion":{"type":"string","maxLength":32},"wordpressVersion":{"type":"string","maxLength":32},"phpVersion":{"type":"string","maxLength":32},"status":{"type":"string","enum":["healthy","attention","offline"]},"packageCount":{"type":"integer","minimum":0}}}}}},"responses":{"200":{"description":"Installation upserted","content":{"application/json":{"schema":{"type":"object","properties":{"installation":{"type":"object","additionalProperties":true},"referralToken":{"type":"string","description":"WordPress only"}}}}}},"400":{"description":"Invalid connector payload","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Tenant mismatch","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Installation ID conflict or installation limit reached","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Registration temporarily unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/connectors/events":{"post":{"tags":["Connectors"],"summary":"Record a connector lifecycle event","description":"Records a funnel event for a registered connector installation. Currently supports `wordpress_embed_created`. Rate-limited per tenant/key. Requires the installation to be registered.","operationId":"recordConnectorEvent","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event","externalInstallationId"],"properties":{"event":{"type":"string","enum":["wordpress_embed_created"]},"externalInstallationId":{"type":"string","format":"uuid"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Event recorded","content":{"application/json":{"schema":{"type":"object","required":["ok","recorded"],"properties":{"ok":{"type":"boolean"},"recorded":{"type":"boolean"}}}}}},"400":{"description":"Invalid event payload","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Installation not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Event delivery failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/lrs/xapi/about":{"get":{"tags":["LRS"],"summary":"xAPI About resource","description":"Unauthenticated. Returns supported xAPI versions (`1.0.0`–`1.0.3`, `2.0.0`). Per xAPI spec, no `X-Experience-API-Version` request header is required.","operationId":"lrsAbout","security":[],"responses":{"200":{"description":"xAPI About payload","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/api/lrs/xapi/statements":{"get":{"tags":["LRS"],"summary":"Query xAPI statements","description":"Retrieve stored xAPI statements with optional filters. `X-Experience-API-Version` required. Supports `statementId`, `voidedStatementId`, `agent`, `verb`, `activity`, `registration`, `since`, `until`, `limit`, `format`, `attachments`, `ascending`. Returns a `StatementResult` object or a single statement. Paginate via `cursor` parameter in `more` URL. Queries run over the 10,000 most recently created statements of the workspace: in a larger workspace an older statement that was stored again recently can fall outside that set, so `since` may not return it.","operationId":"lrsGetStatements","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string","example":"1.0.3"}},{"name":"statementId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"voidedStatementId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"agent","in":"query","schema":{"type":"string","description":"JSON-encoded Agent object"}},{"name":"verb","in":"query","schema":{"type":"string","format":"iri"}},{"name":"activity","in":"query","schema":{"type":"string","format":"iri"}},{"name":"registration","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":0}},{"name":"format","in":"query","schema":{"type":"string","enum":["ids","exact","canonical"]}},{"name":"attachments","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"ascending","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"cursor","in":"query","schema":{"type":"string","description":"Pagination cursor from `more` URL"}}],"responses":{"200":{"description":"StatementResult or single Statement","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid query parameter","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["LRS"],"summary":"Store xAPI statements (batch)","description":"Store one or more xAPI statements (JSON array or single object). Also accepts `multipart/mixed` with inline attachment payloads. `X-Experience-API-Version` required. Immutability enforced: re-posting an identical statement is a no-op; re-posting with different content returns 409.","operationId":"lrsPostStatements","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"array","items":{"type":"object","additionalProperties":true}},{"type":"object","additionalProperties":true,"description":"Single xAPI Statement"}]}},"multipart/mixed":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Array of stored statement UUIDs","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid or non-conformant statement; or `SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Immutability conflict; or `SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"Statement exceeds size limit","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["LRS"],"summary":"Store a single xAPI statement (PUT)","description":"Idempotent single-statement write. Requires `statementId` query parameter. Returns 204 on success, 409 on immutability conflict.","operationId":"lrsPutStatement","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"statementId","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Single xAPI Statement"}}}},"responses":{"204":{"description":"Statement stored"},"400":{"description":"Invalid statement or missing statementId; or `SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Immutability conflict; or `SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/lrs/xapi/activities":{"get":{"tags":["LRS"],"summary":"Get canonical Activity object","description":"Returns the full canonical Activity (merge of all definitions seen). Definition is omitted when the LRS has never seen the activity.","operationId":"lrsGetActivity","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string","format":"iri"}}],"responses":{"200":{"description":"Activity object","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"activityId required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/lrs/xapi/activities/state":{"get":{"tags":["LRS"],"summary":"Get / list Activity State document(s)","description":"Single document (with `stateId`) or list of state IDs (without).","operationId":"lrsGetActivityState","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string"}},{"name":"registration","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"stateId","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"State document or list of state IDs","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"State not found"}}},"put":{"tags":["LRS"],"summary":"Create / replace an Activity State document","operationId":"lrsPutActivityState","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string"}},{"name":"stateId","in":"query","required":true,"schema":{"type":"string"}},{"name":"registration","in":"query","schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}},"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"204":{"description":"Stored"},"400":{"description":"Invalid; or `SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["LRS"],"summary":"Merge into an Activity State document","operationId":"lrsPostActivityState","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string"}},{"name":"stateId","in":"query","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"204":{"description":"Merged"},"400":{"description":"Invalid; or `SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["LRS"],"summary":"Delete Activity State document(s)","operationId":"lrsDeleteActivityState","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string"}},{"name":"stateId","in":"query","schema":{"type":"string","description":"Omit to delete all states for this agent+activity"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"responses":{"204":{"description":"Deleted"},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/lrs/xapi/activities/profile":{"get":{"tags":["LRS"],"summary":"Get / list Activity Profile document(s)","operationId":"lrsGetActivityProfile","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Profile document or list of IDs","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not found"}}},"put":{"tags":["LRS"],"summary":"Create / replace an Activity Profile document","operationId":"lrsPutActivityProfile","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"query","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"204":{"description":"Stored"},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["LRS"],"summary":"Merge into an Activity Profile document","operationId":"lrsPostActivityProfile","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"query","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"204":{"description":"Merged"},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["LRS"],"summary":"Delete an Activity Profile document","operationId":"lrsDeleteActivityProfile","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"activityId","in":"query","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"query","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"responses":{"204":{"description":"Deleted"},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/lrs/xapi/agents":{"get":{"tags":["LRS"],"summary":"Get Person object for an agent","description":"Returns a Person object aggregating every name/identifier the LRS has seen for the queried agent's inverse-functional identifier.","operationId":"lrsGetAgent","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string","description":"JSON-encoded Agent object"}}],"responses":{"200":{"description":"Person object","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"agent required or invalid","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/lrs/xapi/agents/profile":{"get":{"tags":["LRS"],"summary":"Get / list Agent Profile document(s)","operationId":"lrsGetAgentProfile","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Profile document or list of IDs","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not found"}}},"put":{"tags":["LRS"],"summary":"Create / replace an Agent Profile document","operationId":"lrsPutAgentProfile","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"query","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"204":{"description":"Stored"},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["LRS"],"summary":"Merge into an Agent Profile document","operationId":"lrsPostAgentProfile","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"query","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"204":{"description":"Merged"},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["LRS"],"summary":"Delete an Agent Profile document","operationId":"lrsDeleteAgentProfile","security":[{"LrsAuth":[]}],"parameters":[{"name":"X-Experience-API-Version","in":"header","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":true,"schema":{"type":"string"}},{"name":"profileId","in":"query","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Read only when the request is made with a signed-in dashboard session and no credential, and then required: the workspace the page that sent it was rendered for. It is compared with the workspace the session is using and never selects or authorizes one. Never read for a Basic, Bearer or `X-API-Key` credential."}],"responses":{"204":{"description":"Deleted"},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: a dashboard session did not state the workspace its page was rendered for. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: a dashboard session states a workspace the session is not using. Nothing was stored. Never answered to a Basic, Bearer or `X-API-Key` credential.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/capabilities":{"get":{"tags":["Graph"],"summary":"Get graph capability flags","description":"Returns tier flags the UI reads to unlock surfaces: `graphRead`, `graphWrite`, `valueModels`, `askYourData`.","operationId":"getGraphCapabilities","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Capability flags envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/ask":{"post":{"tags":["Graph"],"summary":"Ask-your-data (free-form question)","description":"Structured answer from a free-form question over capability data. Requires `askYourData` tier.","operationId":"graphAsk","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["question"],"properties":{"question":{"type":"string"}}}}}},"responses":{"200":{"description":"Structured answer envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"question required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"Tier not available","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/skills":{"get":{"tags":["Graph"],"summary":"List tenant skill taxonomy","description":"Requires `graphRead` tier and `internal_product` or `admin` scope.","operationId":"listGraphSkills","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Skills envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Graph"],"summary":"Add a custom skill","description":"Appends a tenant-custom skill to the taxonomy. Requires `graphWrite` tier.","operationId":"createGraphSkill","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"domain":{"type":"string"},"parent_id":{"type":"string"},"decay_profile":{"type":"string"}}}}}},"responses":{"201":{"description":"Created skill","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"name required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/roles":{"get":{"tags":["Graph"],"summary":"List roles","description":"Returns tenant roles. Requires `graphRead` tier. Also available to `public_api` keys that list `cale:graph:read` explicitly (keys minted before CALE permissions do not qualify). Rate limited per key.","operationId":"listGraphRoles","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Roles envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized, revoked or expired key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Graph"],"summary":"Create a role","description":"Creates a new role. Required skills define the gap denominator. Requires `graphWrite` tier.","operationId":"createGraphRole","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"Created role","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"name required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/role-templates":{"get":{"tags":["Graph"],"summary":"List curated role templates","description":"Returns the static O*NET / ESCO role template library. Requires `graphWrite` tier to read (write-gated to prevent misuse by read-only callers).","operationId":"listGraphRoleTemplates","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Role templates","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Graph"],"summary":"Create a role from a curated template","description":"Creates the template role and its required skills, seeding the base taxonomy first. Idempotent by role name: an existing role returns 200. `internal_product` or `admin` scope and `graphWrite` tier.","operationId":"createGraphRoleFromTemplate","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["template_key"],"properties":{"template_key":{"type":"string"}}}}}},"responses":{"200":{"description":"Role already existed","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"201":{"description":"Role created","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"template_key must be one of the published role templates","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/roles/{roleId}/requirements":{"get":{"tags":["Graph"],"summary":"Get a role's required-skill levels","description":"Requires `graphRead` tier. A role outside the workspace returns an empty requirement list. Also available to `public_api` keys that list `cale:graph:read` explicitly (keys minted before CALE permissions do not qualify). Rate limited per key.","operationId":"listGraphRoleRequirements","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"roleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Requirements envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid role ID","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized, revoked or expired key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Graph"],"summary":"Replace a role's required-skill set (PUT semantics)","operationId":"setGraphRoleRequirements","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"roleId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["requirements"],"properties":{"requirements":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"responses":{"200":{"description":"Updated requirements","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid requirements","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/learners":{"get":{"tags":["Graph"],"summary":"List learner readiness rollups","description":"Per-learner readiness + org decay split. Requires `graphRead` tier. Optional `?limit` and `?organizationId`.","operationId":"listGraphLearners","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer"}},{"name":"organizationId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Learner readiness envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"`WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/learners/{userId}/skills":{"get":{"tags":["Graph"],"summary":"Get a learner's verified capabilities","description":"Decay-adjusted \"right now\" capability profile. Requires `graphRead` tier. Also available to `public_api` keys that list `cale:learner-skills:read` and are bound to the client system named in `clientSystemId`; `userId` is then that system's subject reference. Tenant scope comes from the key. Rate limited per key (`X-RateLimit-*`).","operationId":"getLearnerSkills","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clientSystemId","in":"query","schema":{"type":"string","maxLength":200},"description":"Client system the learner belongs to. Required for `public_api` keys; optional for internal callers."}],"responses":{"200":{"description":"Learner skills envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid userId encoding, or clientSystemId missing for a public_api key (CLIENT_SYSTEM_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized, revoked or expired key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission or client-system binding denied; `WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Client system not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/learners/{userId}/gaps":{"get":{"tags":["Graph"],"summary":"Get a learner's skill gaps","description":"Gap vs. required levels. Optional `?role` to compute against a specific role. Requires `graphRead` tier. Also available to `public_api` keys that list `cale:learner-skills:read` and are bound to the client system named in `clientSystemId`; `userId` is then that system's subject reference. Tenant scope comes from the key. Rate limited per key (`X-RateLimit-*`).","operationId":"getLearnerGaps","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clientSystemId","in":"query","schema":{"type":"string","maxLength":200},"description":"Client system the learner belongs to. Required for `public_api` keys; optional for internal callers."},{"name":"role","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Gaps envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid userId encoding, or clientSystemId missing for a public_api key (CLIENT_SYSTEM_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized, revoked or expired key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission or client-system binding denied; `WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Client system not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/learners/{userId}/history":{"get":{"tags":["Graph"],"summary":"Get a learner's mastery timeline","description":"Sparse mastery timeline (meaningful transitions, newest first). Optional `?limit`. Requires `graphRead` tier. Also available to `public_api` keys that list `cale:learner-skills:read` and are bound to the client system named in `clientSystemId`; `userId` is then that system's subject reference. Tenant scope comes from the key. Rate limited per key (`X-RateLimit-*`).","operationId":"getLearnerHistory","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clientSystemId","in":"query","schema":{"type":"string","maxLength":200},"description":"Client system the learner belongs to. Required for `public_api` keys; optional for internal callers."},{"name":"limit","in":"query","schema":{"type":"integer","maximum":500}}],"responses":{"200":{"description":"History envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid userId encoding, or clientSystemId missing for a public_api key (CLIENT_SYSTEM_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized, revoked or expired key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission or client-system binding denied; `WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Client system not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/learners/{userId}/next":{"get":{"tags":["Graph"],"summary":"Get ranked gap-closing content for a learner","description":"\"What to learn next\". Optional `?role`. Requires `graphRead` tier. Also available to `public_api` keys that list `cale:learner-skills:read` and are bound to the client system named in `clientSystemId`; `userId` is then that system's subject reference. Tenant scope comes from the key. Rate limited per key (`X-RateLimit-*`).","operationId":"getLearnerNext","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clientSystemId","in":"query","schema":{"type":"string","maxLength":200},"description":"Client system the learner belongs to. Required for `public_api` keys; optional for internal callers."},{"name":"role","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Next content envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid userId encoding, or clientSystemId missing for a public_api key (CLIENT_SYSTEM_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized, revoked or expired key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission or client-system binding denied; `WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Client system not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/learners/{userId}/nudges":{"get":{"tags":["Graph"],"summary":"Get re-cert nudges for a learner","description":"Skills slipping out of currency. Requires `graphRead` tier. Also available to `public_api` keys that list `cale:learner-skills:read` and are bound to the client system named in `clientSystemId`; `userId` is then that system's subject reference. Tenant scope comes from the key. Rate limited per key (`X-RateLimit-*`).","operationId":"getLearnerNudges","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clientSystemId","in":"query","schema":{"type":"string","maxLength":200},"description":"Client system the learner belongs to. Required for `public_api` keys; optional for internal callers."}],"responses":{"200":{"description":"Nudges envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid userId encoding, or clientSystemId missing for a public_api key (CLIENT_SYSTEM_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized, revoked or expired key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphRead tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission or client-system binding denied; `WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Client system not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/learners/{userId}/roles":{"put":{"tags":["Graph"],"summary":"Set role assignments for a learner","description":"Replaces all role assignments. Powers /gaps + coverage. Requires `graphWrite` tier.","operationId":"setLearnerRoles","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["role_ids"],"properties":{"role_ids":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"Updated role assignments","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/content-tags":{"post":{"tags":["Graph"],"summary":"Submit content→skill tags","description":"Create → Connect tag write path. Works on zero-launch content (cold-start). `source` can be `author` (authoring tools) or `ai` (auto-tagging). Requires `graphWrite` tier.","operationId":"submitContentTags","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","minItems":1,"items":{"type":"object","description":"Each tag needs activityId + relation + a skill ref","additionalProperties":true}}}}}}},"responses":{"200":{"description":"Tags written","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"tags must be a non-empty array","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/tags/{mappingId}/review":{"post":{"tags":["Graph"],"summary":"Review an AI-proposed content tag","description":"Approve, reject, or edit an AI-proposed content→skill mapping. Requires `graphWrite` tier. The mapping becomes human-owned and every decision appends an immutable before/after revision naming the API key. Also available to `public_api` keys that list `cale:mappings:review` (no other permission implies it). A mapping in another workspace returns 404. Rate limited per key.","operationId":"reviewContentTagMapping","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"mappingId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["decision"],"properties":{"decision":{"type":"string","enum":["approve","reject","edit"]},"relation":{"type":"string","enum":["teaches","assesses"],"description":"For edit decisions"},"weight":{"type":"number","minimum":0,"maximum":1,"description":"For edit decisions"},"assessedLevel":{"type":["string","null"],"enum":["novice","working","proficient","expert",null],"description":"For edit decisions on an `assesses` mapping: the highest level the item is built to prove. Its score counts toward the top of that level and no further. `null` clears it."}}}}}},"responses":{"200":{"description":"Review result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid decision, relation, weight, assessed level or mapping ID","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized, revoked or expired key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CALE permission denied, or a dashboard session that is not a workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Mapping not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"ASSESSED_LEVEL_NEEDS_ASSESSES: a level on a mapping that does not assess the skill","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/taxonomy/seed":{"post":{"tags":["Graph"],"summary":"Seed the base taxonomy","description":"Seeds the canonical O*NET + ESCO base taxonomy for the tenant. Idempotent — skips skills that already exist. Requires `graphWrite` tier.","operationId":"seedGraphTaxonomy","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"201":{"description":"Seed result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/value/inputs":{"get":{"tags":["Graph"],"summary":"Get value-model inputs","description":"Returns tunable ROI assumptions (costs, probabilities). Requires `valueModels` tier.","operationId":"getValueModelInputs","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Value model inputs envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"valueModels tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Graph"],"summary":"Update value-model inputs","description":"Updates supplied tunable inputs; omitted inputs are unchanged. POST is retained as a compatibility alias. Unknown keys, nonnumeric values, and negative values are rejected. Requires `valueModels` tier.","operationId":"setValueModelInputs","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"loadedDailyCostCents":{"type":"number","minimum":0},"externalHireCostCents":{"type":"number","minimum":0},"rampCostCents":{"type":"number","minimum":0},"internalTrainingCostCents":{"type":"number","minimum":0},"incidentCostCents":{"type":"number","minimum":0},"incidentProbability":{"type":"number","minimum":0},"daysSavedPerRamp":{"type":"number","minimum":0},"workingHoursPerDay":{"type":"number","minimum":0},"avgSessionHours":{"type":"number","minimum":0},"platformCostCents":{"type":"number","minimum":0},"contentDeliveryCostCents":{"type":"number","minimum":0},"learnerHourlyCostCents":{"type":"number","minimum":0},"costPerSkillAcquisitionCents":{"type":"number","minimum":0}},"description":"Subset of supported finite, nonnegative model inputs. An empty object leaves inputs unchanged."}}}},"responses":{"200":{"description":"Updated inputs","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON, unknown input key, or invalid numeric value","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"valueModels tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/graph/value/snapshot":{"get":{"tags":["Graph"],"summary":"Get ROI snapshot for a period","description":"Computes on-demand return on training spend for a period. Accepts `?period=2026-Q2` or explicit `?period_start` / `?period_end` (epoch ms). Only current periods compute; past periods read saved observations. Requires `valueModels` tier and internal_product/admin scope. Metadata preserves snapshotState (available/missing/stale), authoritative snapshotComputedAt (ISO time or null), and response generatedAt. Legacy meta.computedAt is the saved computation time when known, otherwise response time; use snapshotComputedAt to determine whether a recorded computation exists. Interactive computation retains existing events.","operationId":"getValueSnapshot","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"period","in":"query","schema":{"type":"string","example":"2026-Q2"}},{"name":"period_start","in":"query","schema":{"type":"integer","description":"Epoch ms"}},{"name":"period_end","in":"query","schema":{"type":"integer","description":"Epoch ms"}},{"name":"performance_impact","in":"query","schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"ROI snapshot envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"period_start must be before period_end","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"valueModels tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/coverage":{"get":{"tags":["Capability"],"summary":"Get current role and organization coverage","description":"Requires graphRead entitlement. The key selects the workspace; role_id optionally filters its roles. Coverage includes assigned learners with missing evidence as unmet requirements. No learner identities are returned.","operationId":"getCapabilityCoverage","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"role_id","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Coverage envelope with role and organization rows","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"Graph tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/skills":{"get":{"tags":["Capability"],"summary":"List tenant skill catalog (public tier)","description":"Read-only access to the tenant skill taxonomy. Available to `public_api` keys.","operationId":"listCapabilitySkills","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Skills envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/content/{packageId}/skills":{"get":{"tags":["Capability"],"summary":"Get skills for a package","description":"Returns the skills a package's activities build/measure, with the assessment-gap flag. Available to `public_api` keys. Each mapping that measures a skill also says what the item demands and what that lets a score prove: `assessedLevel` (a level set outright, or null), `demandRatings` (ladder id → step id, or null), `demonstrationMode` (or null), `passMarkScaled` (a stored pass mark, or null), `skillNature`, `skillLadders` (every ladder the skill’s rule reads, the one it is measured on first), `skillProfile` (the skill’s own profile, or null) and `evidenceReach` (`basis`: `unrated` | `reviewer_level` | `framework`; `level`; `ceiling` on the 0–100 measure; `reasonCode`; a plain-language `reason`; `frameworkVersion`). All are additive.","operationId":"getPackageCapabilitySkills","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Package skills envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/mappings/review":{"post":{"tags":["Capability"],"summary":"Accept or reject content skill mappings","description":"Accepts or rejects up to 200 content-to-skill mappings in the caller's workspace. For the Allure LMS service and `internal_product`/`admin` keys only; customer `public_api` keys use `/api/v1/graph/tags/{mappingId}/review`. Idempotent: a decision that already stands reports `changed: false`. Unknown or other-workspace ids return `not_found`. Every change appends an audited revision naming the reviewer and the optional note. Requires `graphWrite`.","operationId":"reviewCapabilityMappings","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["mappingIds","decision"],"properties":{"mappingIds":{"type":"array","minItems":1,"maxItems":200,"items":{"type":"string"}},"decision":{"type":"string","enum":["accepted","rejected"]},"note":{"type":"string","maxLength":1000},"reviewerId":{"type":"string","maxLength":120}}}}}},"responses":{"200":{"description":"Review results envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/mappings/{mappingId}/assessed-level":{"put":{"tags":["Capability"],"summary":"Set the level an assessing item proves","description":"Says which level a content-to-skill mapping that measures a skill (`relation: \"assesses\"`) is built to prove. A score on that item then counts toward the top of that level and no further: novice 0–24, working 25–49, proficient 50–74, expert 75–100. `\"assessedLevel\": null` clears it, and the score is read on the whole scale again. For the Allure LMS service and `internal_product`/`admin` keys only. The write changes the level and nothing else. It is not a review decision: a pending mapping stays pending and an accepted one stays accepted, and `status` in the answer says which. A rejected mapping is refused with 409 `MAPPING_REJECTED`; accept it in a review first. Each change appends an audited revision naming the reviewer. Idempotent: the level a mapping already has answers `changed: false`. `assessedLevel` in the answer is the level read back from the stored mapping. A mapping in another workspace is indistinguishable from a missing one. A signed-in dashboard session may use it only as an active workspace owner or admin. Requires `graphWrite`.","operationId":"setCapabilityMappingAssessedLevel","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"mappingId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["assessedLevel"],"properties":{"assessedLevel":{"type":["string","null"],"enum":["novice","working","proficient","expert",null],"description":"`null` clears the level."},"reviewerId":{"type":"string","pattern":"^[A-Za-z0-9_.:@-]{1,120}$","description":"The member making the change. Stored after the credential on the revision."}}}}}},"responses":{"200":{"description":"Level result","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["mappingId","status","changed","assessedLevel"],"properties":{"mappingId":{"type":"string"},"status":{"type":"string","enum":["pending","accepted"],"description":"The mapping's review status, which this write never changes."},"changed":{"type":"boolean"},"assessedLevel":{"type":["string","null"],"enum":["novice","working","proficient","expert",null]}}}}}}}},"400":{"description":"Invalid request (INVALID_JSON, VALIDATION_ERROR, INVALID_ASSESSED_LEVEL)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Mapping not found in this workspace (MAPPING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"The mapping was rejected (MAPPING_REJECTED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"The mapping does not measure a skill (ASSESSED_LEVEL_NEEDS_ASSESSES)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/mappings/{mappingId}/evidence-attributes":{"put":{"tags":["Capability"],"summary":"Say what an assessing item demands","description":"Records what a content-to-skill mapping that measures a skill (`relation: \"assesses\"`) demands of the learner: its rating on one or more demand ladders (`demandRatings`, ladder id → step id) and how real the demonstration is (`demonstrationMode`). The built-in ladders are `thinking` (remember, understand, apply, analyze, evaluate, create), `relating` (notice, respond, value, choose, live) and `doing` (follow, perform, refine, fluent, adapt). This release accepts only these built-in ladders. With no level set through `/assessed-level`, these and the kind of skill decide the highest level a score on the item can prove. A level set through `/assessed-level` is an override and still wins. `null` clears a value; a key left out is not changed. Scores already recorded are not changed: this applies to evidence from then on. For the Allure LMS service and `internal_product`/`admin` keys only. The write changes these values and nothing else. It is not a review decision: a pending mapping stays pending and an accepted one stays accepted, and `status` in the answer says which. A rejected mapping is refused with 409 `MAPPING_REJECTED`; accept it in a review first. Each change appends an audited revision naming the reviewer. Idempotent: values a mapping already holds answer `changed: false`. `demandRatings`, `demonstrationMode` and `passMarkScaled` in the answer are what the stored mapping holds after the write (`null` when not set), not an echo of the request. A mapping in another workspace is indistinguishable from a missing one. A signed-in dashboard session may use it only as an active workspace owner or admin. Requires `graphWrite`.","operationId":"setCapabilityMappingEvidenceAttributes","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"mappingId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"description":"At least one of `demandRatings`, `demonstrationMode` and `passMarkScaled`. `reviewerId` on its own changes nothing and is refused.","anyOf":[{"required":["demandRatings"]},{"required":["demonstrationMode"]},{"required":["passMarkScaled"]}],"properties":{"demandRatings":{"type":["object","null"],"propertyNames":{"pattern":"^[a-z][a-z0-9_]{0,39}$"},"additionalProperties":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"maxProperties":8,"description":"Ladder id → step id, replaced as a whole. `null` or `{}` clears the ratings. Each id is lower case, starts with a letter and is at most 40 characters."},"demonstrationMode":{"type":["string","null"],"enum":["knowledge_check","applied_exercise","simulated_performance","observed_performance","sustained_performance",null],"description":"`null` clears it."},"passMarkScaled":{"type":["number","null"],"exclusiveMinimum":0,"maximum":1,"description":"The item’s own pass mark as a scaled score, used when a result carries none. A score is then read against it: reaching it lands on the lower bound of the level the item can prove, full marks on the top. `null` clears it."},"reviewerId":{"type":"string","pattern":"^[A-Za-z0-9_.:@-]{1,120}$","description":"The member making the change. Stored after the credential on the revision."}}}}}},"responses":{"200":{"description":"Attribute result","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["mappingId","status","changed","demandRatings","demonstrationMode","passMarkScaled"],"properties":{"mappingId":{"type":"string"},"status":{"type":"string","enum":["pending","accepted"],"description":"The mapping's review status, which this write never changes."},"changed":{"type":"boolean"},"demandRatings":{"type":["object","null"],"additionalProperties":{"type":"string"},"description":"The ratings the stored mapping holds; `null` when it holds none."},"demonstrationMode":{"type":["string","null"],"enum":["knowledge_check","applied_exercise","simulated_performance","observed_performance","sustained_performance",null]},"passMarkScaled":{"type":["number","null"]}}}}}}}},"400":{"description":"Invalid request (INVALID_JSON, VALIDATION_ERROR, INVALID_DEMAND_RATINGS, INVALID_DEMONSTRATION_MODE, INVALID_PASS_MARK, INVALID_EVIDENCE_ATTRIBUTES)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden, or a dashboard session that is not an active workspace owner or admin (WORKSPACE_ADMIN_REQUIRED, CUSTOMER_ORIGIN_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Mapping not found in this workspace (MAPPING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"The mapping was rejected (MAPPING_REJECTED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"The mapping does not measure a skill (EVIDENCE_ATTRIBUTES_NEED_ASSESSES)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/evidence-framework":{"get":{"tags":["Capability"],"summary":"Read the evidence-and-level framework for this workspace","description":"Built-in demand ladders, demonstration modes, skill natures and default profiles, level scales and default surface settings. Requires `graphWrite`.","operationId":"getCapabilityEvidenceFramework","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Framework","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["frameworkVersion","ladders","demonstrationModes","skillNatures","profiles","scales","surfaces"],"properties":{"frameworkVersion":{"type":"string"},"frameworkVersions":{"type":"array","items":{"type":"string"}},"ladders":{"type":"object","properties":{"builtIn":{"type":"array","items":{"type":"object"}},"custom":{"type":"array","items":{"type":"object"}}}},"demonstrationModes":{"type":"array","items":{"type":"object"}},"skillNatures":{"type":"array","items":{"type":"object"}},"profiles":{"type":"object","additionalProperties":true},"scales":{"type":"object","properties":{"builtIn":{"type":"array","items":{"type":"object"}},"custom":{"type":"array","items":{"type":"object"}}}},"displayScaleId":{"type":["string","null"]},"surfaces":{"type":"object","additionalProperties":{"type":"object","properties":{"scaleId":{"type":"string"},"isSurfaceDefault":{"type":"boolean"}}}},"limits":{"type":"object","additionalProperties":true}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/skill-links":{"post":{"tags":["Capability"],"summary":"Link two skills","description":"Says that one skill is a prerequisite of another, or that two skills are related, in the caller's workspace. A `prerequisite` link points from the prerequisite (`fromSkillId`) to the skill it unlocks (`toSkillId`). A `related` link has no direction: A to B and B to A are the same link. For the Allure LMS service and `internal_product`/`admin` keys only; customer `public_api` keys cannot edit the skill map. Idempotent: a link that already stands answers 200 with `changed: false`. A new link answers 201. Sending a different `weight` for an existing link replaces it and keeps who created the link and when; the weight change is written to the audit log. Omitting `weight` keeps the stored one. Both skills must be active skills in the workspace. A pair holds one link type at a time. A prerequisite that would make any skill its own prerequisite is refused (`PREREQUISITE_CYCLE`). A change that alters the published graph changes the graph `checksum` returned here and by `/api/v1/cale/graph/query`, and advances `revision` in workspaces that store graph revisions. Requires `graphWrite`.","operationId":"createCapabilitySkillLink","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fromSkillId","toSkillId","type"],"properties":{"fromSkillId":{"type":"string","minLength":1,"maxLength":200,"description":"For `prerequisite`: the prerequisite skill."},"toSkillId":{"type":"string","minLength":1,"maxLength":200,"description":"For `prerequisite`: the skill it unlocks."},"type":{"type":"string","enum":["prerequisite","related"]},"weight":{"type":"number","minimum":0,"maximum":1},"actorId":{"type":"string","pattern":"^[A-Za-z0-9_.:@-]{1,120}$","description":"The member making the change. Stored after the credential in `createdBy`."}}}}}},"responses":{"200":{"description":"The link already stood (`changed: false`)","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["changed","link","graph"],"properties":{"changed":{"type":"boolean"},"link":{"type":"object","required":["fromSkillId","toSkillId","type","weight","source","status","createdBy","createdAt"],"properties":{"fromSkillId":{"type":"string"},"toSkillId":{"type":"string"},"type":{"type":"string","enum":["prerequisite","related"]},"weight":{"type":["number","null"]},"source":{"type":["string","null"],"enum":["human","ai",null]},"status":{"type":"string","enum":["accepted"]},"createdBy":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"}}},"graph":{"type":"object","required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}}},"201":{"description":"Link created","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["changed","link","graph"],"properties":{"changed":{"type":"boolean"},"link":{"type":"object","required":["fromSkillId","toSkillId","type","weight","source","status","createdBy","createdAt"],"properties":{"fromSkillId":{"type":"string"},"toSkillId":{"type":"string"},"type":{"type":"string","enum":["prerequisite","related"]},"weight":{"type":["number","null"]},"source":{"type":["string","null"],"enum":["human","ai",null]},"status":{"type":"string","enum":["accepted"]},"createdBy":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"}}},"graph":{"type":"object","required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}}},"400":{"description":"Invalid request (INVALID_JSON, VALIDATION_ERROR, SELF_LINK_NOT_ALLOWED, INVALID_WEIGHT, INVALID_ACTOR, INVALID_LINK_TYPE)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Skill or workspace not found (SKILL_NOT_FOUND, TENANT_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Conflicts with the current map (PREREQUISITE_CYCLE, LINK_TYPE_CONFLICT)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"A skill cannot be linked (PROPOSED_SKILL_NOT_ACCEPTABLE, RETIRED_SKILL_NOT_ACCEPTABLE, REPLACED_SKILL_NOT_ACCEPTABLE) or the map is too large to check (LINK_CHECK_LIMIT_EXCEEDED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["Capability"],"summary":"Remove a link between two skills","description":"Removes the link named in the JSON body. A `related` link is found in either order; a `prerequisite` link only in the order given. Idempotent: a link that is not there answers 200 with `changed: false`. Skills of any lifecycle can be unlinked. Each removal is written to the audit log with the caller and the optional `actorId`. Same callers and tier as creating a link.","operationId":"removeCapabilitySkillLink","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fromSkillId","toSkillId","type"],"properties":{"fromSkillId":{"type":"string","minLength":1,"maxLength":200},"toSkillId":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["prerequisite","related"]},"actorId":{"type":"string","pattern":"^[A-Za-z0-9_.:@-]{1,120}$","description":"The member removing the link. Recorded after the credential in the audit log."}}}}}},"responses":{"200":{"description":"Removal result","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["changed","removed","graph"],"properties":{"changed":{"type":"boolean"},"removed":{"type":"integer","minimum":0},"graph":{"type":"object","required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}}},"400":{"description":"Invalid request (INVALID_JSON, VALIDATION_ERROR, SELF_LINK_NOT_ALLOWED, INVALID_LINK_TYPE)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Skill or workspace not found (SKILL_NOT_FOUND, TENANT_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/library/search":{"get":{"tags":["Capability"],"summary":"Search the Allure skill library","description":"Searches or lists the shared Allure skill library: skills, knowledge, abilities, competencies, tasks, work activities, tools, roles and groupings drawn from open data sources (O*NET, ESCO, NIST NICE, OPM and others) in one format. The answer depends on the library alone: nothing about the caller's workspace is read or returned, and nothing here changes a workspace. With `q`: a relevance search over names and other names, then descriptions, paged up to 200 results. Without `q`: give `parent` to list the items directly under one item, or both `source` and `kind` to list that source's top-level items, in name order. Only cleared, active items are returned: material that is held for licence review or waiting for content review is never listed. By default only `standard` items are returned (high or medium confidence, and not placed by inheritance); `includeLowConfidence=true` also returns the rest, each marked in `quality`. For the scoped Allure LMS service, `internal_product`/`admin` API keys, or a Clerk dashboard session with an active owner, admin, billing, analyst or support workspace membership. Requires `graphWrite` (Professional/Enterprise or the existing managed/grandfathered entitlement).","operationId":"searchCapabilityLibrary","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]},{"ClerkSession":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","minLength":2,"maxLength":200},"description":"Search text."},{"name":"kind","in":"query","required":false,"schema":{"type":"string","enum":["skill","knowledge","ability","competency","task","work_activity","tool","role","category","level"]}},{"name":"source","in":"query","required":false,"schema":{"type":"string"},"description":"A source key, for example `onet` or `esco`."},{"name":"parent","in":"query","required":false,"schema":{"type":"string"},"description":"A library item id. Only items directly under it."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":600},"description":"`nextCursor` from the previous page of the same request."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"includeLowConfidence","in":"query","required":false,"schema":{"type":"string","enum":["true","false"],"default":"false"},"description":"Also return `extended` items: low confidence, or placed by inheritance and not reviewed row by row."}],"responses":{"200":{"description":"A page of library items","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["items","nextCursor"],"properties":{"items":{"type":"array","items":{"type":"object","required":["id","kind","name","description","parentId","source","quality","home","thirdPartyTrademark"],"properties":{"id":{"type":"string","description":"Allure's own stable id for the item."},"kind":{"type":"string","enum":["skill","knowledge","ability","competency","task","work_activity","tool","role","category","level"],"description":"`ability` is what the alignment calls an attribute, `task` a task statement, `role` an occupation and `category` a grouping."},"name":{"type":"string"},"description":{"type":["string","null"]},"parentId":{"type":["string","null"]},"source":{"type":"string","description":"The source the item came from, or `allure`."},"quality":{"type":"object","required":["confidence","reviewStanding","tier"],"description":"How sure the alignment is of the item, and how it came to be placed.","properties":{"confidence":{"type":["string","null"],"enum":["high","medium","low",null]},"reviewStanding":{"type":["string","null"],"enum":["reviewed","inherited","backbone",null],"description":"`reviewed`: judged row by row. `inherited`: placed from something else that was reviewed. `backbone`: a record of the classification the others were aligned to."},"tier":{"type":"string","enum":["standard","extended"],"description":"`standard` (high or medium confidence, not placed by inheritance) is returned by default. `extended` is returned only with `includeLowConfidence=true`."}}},"home":{"type":["object","null"],"required":["areaId","areaName","groupId","groupName","group2Id","group2Name"],"description":"Where the item sits in Allure's own hierarchy: its area, its group, and a second group when it belongs to two. `null` for an item that was never placed.","properties":{"areaId":{"type":"string"},"areaName":{"type":["string","null"]},"groupId":{"type":["string","null"]},"groupName":{"type":["string","null"]},"group2Id":{"type":["string","null"]},"group2Name":{"type":["string","null"]}}},"thirdPartyTrademark":{"type":"boolean","description":"A third-party product name: a trademark of its owner."}}}},"nextCursor":{"type":["string","null"],"description":"`null` when there is nothing more. A page can hold fewer than `limit` items and still have a next page."}}}}}}}},"400":{"description":"Invalid request (VALIDATION_ERROR, LIBRARY_BROWSE_SCOPE_REQUIRED, LIBRARY_CURSOR_INVALID)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Parent item not found (LIBRARY_PARENT_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"The search cannot be paged this far (LIBRARY_SEARCH_WINDOW_EXCEEDED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/library/items/{itemId}":{"get":{"tags":["Capability"],"summary":"Read one library item with its origin and links","description":"One library item: what it is, where it came from, the parents above it and the items it is linked to. `origin` is a bounded page of at most ten source records; follow `originNextCursor` until null. `nameOrigins` identifies every returned name and alias by source and record id. Each origin entry has the source, its version and licence, the source's own id and name for the record, and `modified` when Allure's wording differs from the source's. `ancestors` is the chain of parents, nearest first. `links` lists related, essential, optional, same-as and prerequisite links whose other end is also available; each says its `source`, which is a source key for structure a source published or `allure` for a link Allure made. A held or not-yet-reviewed item answers 404 exactly like one that does not exist. For the scoped Allure LMS service, `internal_product`/`admin` API keys, or a Clerk dashboard session with an active owner, admin, billing, analyst or support workspace membership. Requires `graphWrite` (Professional/Enterprise or the existing managed/grandfathered entitlement).","operationId":"getCapabilityLibraryItem","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]},{"ClerkSession":[]}],"parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"string","pattern":"^asl_[a-z0-9]{8,40}$"}},{"name":"originCursor","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":46},"description":"originNextCursor from the previous read of the same item; continue until null for the complete visible record list."},{"name":"includeLowConfidence","in":"query","required":false,"schema":{"type":"string","enum":["true","false"],"default":"false"},"description":"Without it an `extended` item answers 404 and is left out of the parents and links of any item read."}],"responses":{"200":{"description":"The library item","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["item","nameOrigins","origin","originNextCursor","ancestors","links","linksTruncated"],"properties":{"item":{"type":"object","required":["id","kind","name","description","parentId","source","quality","home","thirdPartyTrademark","aliases","labels","levelScale","levelAnchors"],"properties":{"id":{"type":"string","description":"Allure's own stable id for the item."},"kind":{"type":"string","enum":["skill","knowledge","ability","competency","task","work_activity","tool","role","category","level"],"description":"`ability` is what the alignment calls an attribute, `task` a task statement, `role` an occupation and `category` a grouping."},"name":{"type":"string"},"description":{"type":["string","null"]},"parentId":{"type":["string","null"]},"source":{"type":"string","description":"The source the item came from, or `allure`."},"quality":{"type":"object","required":["confidence","reviewStanding","tier"],"description":"How sure the alignment is of the item, and how it came to be placed.","properties":{"confidence":{"type":["string","null"],"enum":["high","medium","low",null]},"reviewStanding":{"type":["string","null"],"enum":["reviewed","inherited","backbone",null],"description":"`reviewed`: judged row by row. `inherited`: placed from something else that was reviewed. `backbone`: a record of the classification the others were aligned to."},"tier":{"type":"string","enum":["standard","extended"],"description":"`standard` (high or medium confidence, not placed by inheritance) is returned by default. `extended` is returned only with `includeLowConfidence=true`."}}},"home":{"type":["object","null"],"required":["areaId","areaName","groupId","groupName","group2Id","group2Name"],"description":"Where the item sits in Allure's own hierarchy: its area, its group, and a second group when it belongs to two. `null` for an item that was never placed.","properties":{"areaId":{"type":"string"},"areaName":{"type":["string","null"]},"groupId":{"type":["string","null"]},"groupName":{"type":["string","null"]},"group2Id":{"type":["string","null"]},"group2Name":{"type":["string","null"]}}},"thirdPartyTrademark":{"type":"boolean","description":"A third-party product name: a trademark of its owner."},"aliases":{"type":"array","items":{"type":"string"}},"labels":{"type":"object","additionalProperties":{"type":"string"}},"levelScale":{"type":["object","null"],"required":["min","max"],"properties":{"scaleId":{"type":"string"},"name":{"type":"string"},"min":{"type":"number"},"max":{"type":"number"}}},"levelAnchors":{"type":"array","items":{"type":"object","required":["value","description"],"properties":{"scaleId":{"type":"string"},"value":{"type":"number"},"description":{"type":"string"}}}}}},"nameOrigins":{"type":"array","description":"Every returned name and alias with its source-record reference, independent of origin pagination. A name can have several contributing records.","items":{"type":"object","required":["name","sourceKey","sourceId"],"properties":{"name":{"type":"string"},"sourceKey":{"type":"string"},"sourceId":{"type":"string"}}}},"originNextCursor":{"type":["string","null"],"description":"Pass as originCursor on the same item read to continue. Null means the record list is complete; held sources are omitted and a page can be empty."},"origin":{"type":"array","items":{"type":"object","required":["sourceKey","sourceName","sourceVersion","sourceId","sourceCode","sourceUrl","licence","originalName","modified"],"properties":{"sourceKey":{"type":"string"},"sourceName":{"type":"string"},"sourceVersion":{"type":"string"},"sourceId":{"type":"string","description":"The source's own id for the record."},"sourceUrl":{"type":["string","null"]},"licence":{"type":"string"},"sourceCode":{"type":["string","null"],"description":"The source's own code for the record, where it publishes one (an ESCO occupation's `2359.1`). Kept as a code, never part of the name."},"originalName":{"type":"string","description":"The source's own name for the record."},"modified":{"type":"boolean","description":"Allure's wording differs from the source's."}}}},"ancestors":{"type":"array","items":{"type":"object","required":["id","kind","name"],"properties":{"id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"}}}},"links":{"type":"array","items":{"type":"object","required":["id","kind","name","type","direction","source"],"properties":{"id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["related","essential","optional","same_as","prerequisite","parent"]},"direction":{"type":"string","enum":["outgoing","incoming"]},"source":{"type":"string","description":"A source key, or `allure` for a link Allure made."}}}},"linksTruncated":{"type":"boolean"}}}}}}}},"400":{"description":"Invalid item id (INVALID_LIBRARY_ITEM_ID), duplicate/unknown/invalid query parameter (VALIDATION_ERROR), or origin cursor (LIBRARY_CURSOR_INVALID)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Library item not found (LIBRARY_ITEM_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/capability/skills/{skillId}/parent":{"put":{"tags":["Capability"],"summary":"Set or clear a skill's parent","description":"Puts a skill under a parent skill in the same workspace, or clears its parent with `\"parentId\": null`. The parent must be an active skill that does not already sit under this skill (`PARENT_CYCLE`). Idempotent: the parent a skill already has answers `changed: false`. Each change is written to the audit log with the caller, the optional `actorId` and the parent before and after. For the Allure LMS service and `internal_product`/`admin` keys only. Requires `graphWrite`.","operationId":"setCapabilitySkillParent","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["parentId"],"properties":{"parentId":{"type":["string","null"],"minLength":1,"maxLength":200},"actorId":{"type":"string","pattern":"^[A-Za-z0-9_.:@-]{1,120}$","description":"The member making the change. Recorded after the credential in the audit log."}}}}}},"responses":{"200":{"description":"Parent result","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["changed","skill","graph"],"properties":{"changed":{"type":"boolean"},"skill":{"type":"object","required":["id","parentId"],"properties":{"id":{"type":"string"},"parentId":{"type":["string","null"]}}},"graph":{"type":"object","required":["revision","checksum"],"properties":{"revision":{"type":"integer","minimum":1},"checksum":{"type":"string","pattern":"^[A-Fa-f0-9]{64}$"}}}}}}}}}},"400":{"description":"Invalid request (INVALID_JSON, VALIDATION_ERROR, INVALID_SKILL_ID, SELF_PARENT_NOT_ALLOWED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Scope forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Skill or workspace not found (SKILL_NOT_FOUND, TENANT_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"The parent already sits under this skill (PARENT_CYCLE)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"The parent cannot be used (PARENT_SKILL_NOT_FOUND, PROPOSED_SKILL_NOT_ACCEPTABLE, RETIRED_SKILL_NOT_ACCEPTABLE, REPLACED_SKILL_NOT_ACCEPTABLE, PARENT_CHAIN_TOO_DEEP)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/skills/extract":{"post":{"tags":["Capability"],"summary":"Trigger skill extraction backfill","description":"Manually or via legacy-library triggers AI skill extraction for a specific package or the whole tenant. Empty body extracts across all tenant content. Requires `graphWrite` tier and `internal_product`/`admin` scope.","operationId":"extractSkills","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"package_id":{"type":"string"},"package_version":{"type":"string"},"requested_by":{"type":"string"}}}}}},"responses":{"202":{"description":"Extraction job accepted","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"graphWrite tier required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/vr/packages":{"post":{"tags":["VR"],"summary":"Register a VR package version","description":"Registers an APK-based VR package version in the Connect catalog.","operationId":"registerVrPackage","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"vrPackageRegistrationSchema payload (see lib/connect-vr-package-service.ts)"}}}},"responses":{"201":{"description":"VR package registered","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"500":{"description":"Registration failed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/customers":{"get":{"tags":["Customer API"],"summary":"List child workspaces","description":"Customer (sub-tenant) API. Requires a parent-scoped key: a LIVE `public_api` key of a top-level workspace created with Customer API access. Growth and up; Scale and Enterprise have unlimited child workspaces and full white-label.","operationId":"listCustomers","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Child workspaces","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED: the Customer API needs Growth or higher","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED: not a parent-scoped LIVE key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer API"],"summary":"Create an isolated child workspace","description":"Creates a child workspace owned by the parent workspace owner, with optional per-child quotas, and by default mints a child API key (secret returned once). Usage rolls up to the parent's bill. Growth parents may hold 25 child workspaces; Scale and Enterprise are unlimited.","operationId":"createCustomer","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":2,"maxLength":120},"slug":{"type":"string"},"mode":{"type":"string","enum":["live","sandbox"]},"quotas":{"type":"object","properties":{"active_learners":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}]},"packages":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}]},"storage_gb":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}}},"create_api_key":{"type":"boolean","default":true}}}}}},"responses":{"201":{"description":"Child workspace (and child API key, once)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request or quota","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED (Customer API needs Growth; more than 25 children needs Scale)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"PARENT_OWNER_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/customers/usage":{"get":{"tags":["Customer API"],"summary":"Rolled-up usage by workspace","description":"Active learners per workspace (parent first, then each child) over the last 30 days, and whether child usage bills on the parent subscription.","operationId":"getCustomerUsage","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Usage breakdown","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/customers/{customerId}":{"get":{"tags":["Customer API"],"summary":"Get a child workspace","operationId":"getCustomer","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Child workspace","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED: the Customer API needs Growth or higher","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not a child of this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"patch":{"tags":["Customer API"],"summary":"Suspend or reactivate a child workspace","operationId":"updateCustomerStatus","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["active","suspended"]}}}}}},"responses":{"200":{"description":"Updated child workspace","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid status","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED: the Customer API needs Growth or higher","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not a child of this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["Customer API"],"summary":"Retire (archive) a child workspace","description":"Archives the child without touching the parent. Data is kept; the child stops serving.","operationId":"archiveCustomer","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Archived child workspace","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED: the Customer API needs Growth or higher","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not a child of this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/customers/{customerId}/quotas":{"patch":{"tags":["Customer API"],"summary":"Set per-child quotas","description":"Per-child quotas: new learners past `active_learners` and new packages past `packages` are refused; `storage_gb` is enforced at publish. `null` clears a quota.","operationId":"setCustomerQuotas","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"active_learners":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}]},"packages":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}]},"storage_gb":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}]}}}}}},"responses":{"200":{"description":"Updated quotas","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid quota","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED: the Customer API needs Growth or higher","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not a child of this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/customers/{customerId}/api-keys":{"post":{"tags":["Customer API"],"summary":"Mint a child API key","operationId":"createCustomerApiKey","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string"},"mode":{"type":"string","enum":["live","test"]}}}}}},"responses":{"201":{"description":"Child API key (secret returned once)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED: the Customer API needs Growth or higher","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not a child of this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/customers/{customerId}/domain":{"put":{"tags":["Customer API"],"summary":"Set a child custom player domain","operationId":"setCustomerDomain","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"anyOf":[{"type":"string"},{"type":"null"}]}}}}}},"responses":{"200":{"description":"Domain set (pending until DNS verifies)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid domain","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not a child of this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"502":{"description":"Hosting provider rejected the domain","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/customers/{customerId}/player-chrome":{"put":{"tags":["Customer API"],"summary":"Set a child branded player","operationId":"setCustomerPlayerChrome","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"customerId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}}},"responses":{"200":{"description":"Player chrome set","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"PLAN_UPGRADE_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"CUSTOMER_API_KEY_REQUIRED","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not a child of this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/usage/spend-cap":{"get":{"tags":["Usage"],"summary":"Get the workspace and per-key spend caps","description":"A spend cap bounds usage charges (active-learner overage) per period. Alerts fire as projected usage charges reach 80% and 100% of the cap (`usage.spend_cap.80` / `usage.spend_cap.100` webhooks); after that, new learners get `402 SPEND_CAP_REACHED` and existing learners keep launching. The lower of the workspace cap and the launching key's cap applies.","operationId":"getSpendCap","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Spend caps","content":{"application/json":{"schema":{"type":"object","properties":{"workspace_cap_cents":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}]},"behavior":{"type":"string"},"key_caps":{"type":"array","items":{"type":"object","properties":{"key_id":{"type":"string"},"label":{"type":"string"},"cap_cents":{"type":"integer"}}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"`WORKSPACE_ROLE_REQUIRED` for a signed-in dashboard session that is not an active workspace owner, admin or billing member","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Usage"],"summary":"Set or remove the workspace spend cap","description":"Body `{ \"cap_cents\": 5000 }` caps usage charges at $50 per period; `{ \"cap_cents\": null }` removes the cap. LIVE keys only.","operationId":"setSpendCap","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["cap_cents"],"properties":{"cap_cents":{"anyOf":[{"type":"integer","minimum":0,"maximum":100000000},{"type":"null"}]}}}}}},"responses":{"200":{"description":"Updated spend cap","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid cap","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"TEST keys, and keys that carry their own spend cap, cannot change billing controls","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/keys/{keyId}/spend-cap":{"put":{"tags":["Usage"],"summary":"Set or remove a per-key spend cap","description":"Launches made with this key stop admitting new learners once projected usage charges would pass the cap (the lower of the key and workspace caps applies). The key must belong to the calling workspace. Body `{ \"cap_cents\": 2000 }` or `{ \"cap_cents\": null }`. LIVE keys only.","operationId":"setApiKeySpendCap","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["cap_cents"],"properties":{"cap_cents":{"anyOf":[{"type":"integer","minimum":0,"maximum":100000000},{"type":"null"}]}}}}}},"responses":{"200":{"description":"Updated key spend cap","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid cap","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"TEST keys, the key itself, and keys that carry their own spend cap cannot change caps","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"API key not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/tenants/me/player-chrome":{"get":{"tags":["Tenants"],"summary":"Get tenant's default player chrome","description":"Returns the stored tenant-level default player chrome settings. Chrome is resolved at session-detail time: `trainingos` origin → `none`; per-dispatch override; then this default.","operationId":"getTenantPlayerChrome","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Player chrome setting","content":{"application/json":{"schema":{"type":"object","properties":{"playerChrome":{"anyOf":[{"type":"object","additionalProperties":true,"description":"PlayerChromeBranding object"},{"type":"null"}]}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Tenants"],"summary":"Set tenant's default player chrome","description":"Stores or clears the tenant-level player chrome override. `mode: \"custom\"` requires Starter plan or above (returns 402 on sandbox/free). Pass `null` or `{ \"mode\": \"inherit\" }` to clear.","operationId":"setTenantPlayerChrome","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true,"description":"PlayerChromeBranding object"},{"type":"null"}]}}}},"responses":{"200":{"description":"Updated player chrome","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"Custom (branded) chrome requires a paid plan; PLAN_UPGRADE_REQUIRED (Growth and up) for workspaces on current plan terms","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/revenue":{"get":{"tags":["Revenue"],"summary":"List seller revenue entries","description":"Returns revenue ledger entries for the tenant. Requires a paid plan. Optional `?period_start`, `?period_end` (epoch ms), `?limit`.","operationId":"listRevenueEntries","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"period_start","in":"query","schema":{"type":"integer"}},{"name":"period_end","in":"query","schema":{"type":"integer"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Revenue entries","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"Paid plan required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Revenue"],"summary":"Record a revenue entry","description":"Appends a sale, refund, or credit to the tenant revenue ledger. Requires a paid plan.","operationId":"createRevenueEntry","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount_cents","kind"],"properties":{"amount_cents":{"type":"integer","minimum":1},"currency":{"type":"string","minLength":3,"maxLength":3},"units":{"type":"integer","minimum":1},"kind":{"type":"string","enum":["sale","refund","credit"]},"package_id":{"type":"string"},"dispatch_id":{"type":"string"},"customer_label":{"type":"string","maxLength":160},"occurred_at":{"type":"string","format":"date-time"}}}}}},"responses":{"201":{"description":"Created revenue entry","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"402":{"description":"Paid plan required","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/contracts":{"get":{"tags":["Packages"],"summary":"Get API contract manifest","description":"Returns the v1 API contract version manifest. No authentication required.","operationId":"getContractManifest","security":[],"responses":{"200":{"description":"API contract manifest","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/api/v1/openapi-actions":{"get":{"tags":["Packages"],"summary":"GPT Actions OpenAPI subset","description":"Unauthenticated OpenAPI 3.1 document tailored for OpenAI GPT Actions (quick-publish, conversions, packages, sessions). Full partner catalog remains at GET /api/docs/openapi.","operationId":"getOpenApiActionsSubset","security":[],"responses":{"200":{"description":"OpenAPI 3.1 JSON for GPT Actions import","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/api/v1/packages/{packageId}/aicc/launch":{"post":{"tags":["Sessions"],"summary":"Launch a package via AICC HACP","description":"Creates a session and returns an AICC HACP launch URL for the given package and user.","operationId":"launchPackageAicc","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user_id"],"properties":{"user_id":{"type":"string","maxLength":512},"au_id":{"type":"string","maxLength":512,"description":"Assignable Unit ID (optional)"}}}}}},"responses":{"200":{"description":"AICC launch payload","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found or no AICC profile","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/packages/{packageId}/cmi5/launch":{"post":{"tags":["Sessions"],"summary":"Launch a package via cmi5","description":"Creates a session and returns a cmi5 launch URL for the given package and actor.","operationId":"launchPackageCmi5","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user_id","actor"],"properties":{"user_id":{"type":"string","maxLength":512},"actor":{"type":"object","additionalProperties":true,"description":"xAPI Actor object"},"registration":{"type":"string","format":"uuid"},"au_id":{"type":"string","format":"uri","description":"Assignable Unit IRI (optional)"}}}}}},"responses":{"200":{"description":"cmi5 launch payload","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found or no cmi5 manifest","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/content/{path}":{"get":{"tags":["Content"],"summary":"Serve a package content asset","description":"Unauthenticated catch-all for serving package content files (HTML, JS, CSS, images, etc.) from R2 storage. The `{path}` component is a catch-all segment. Demo packages use a short-lived signed cookie for access control. Returns the raw file bytes with appropriate Content-Type and privacy headers.","operationId":"getPackageContentAsset","security":[],"parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string"},"description":"Catch-all asset path relative to the tenant content root"}],"responses":{"200":{"description":"Asset bytes","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"302":{"description":"Redirect to presigned download URL"},"403":{"description":"Demo access denied"},"404":{"description":"Asset not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/scorm/packages/{packageId}":{"get":{"tags":["SCORM"],"summary":"Get a SCORM package (legacy)","description":"Returns SCORM package detail in the legacy shape. Prefer `/api/v1/packages/{packageId}`.","operationId":"getLegacyScormPackage","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Legacy SCORM package detail","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["SCORM"],"summary":"Archive a SCORM package (legacy)","description":"Archives the package. Prefer `/api/v1/packages/{packageId}` DELETE.","operationId":"archiveLegacyScormPackage","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Archived","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/scorm/packages/{packageId}/launch":{"post":{"tags":["SCORM"],"summary":"Launch a SCORM package (legacy)","description":"Creates a session and returns a legacy SCORM launch payload. Prefer `/api/v1/packages/{packageId}/launch`.","operationId":"launchLegacyScormPackage","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user_id"],"properties":{"user_id":{"type":"string"},"session_id":{"type":"string","format":"uuid"},"context":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Legacy SCORM launch payload","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/scorm/sessions/{sessionId}":{"get":{"tags":["SCORM"],"summary":"Get a SCORM session (legacy)","description":"Returns a session in the legacy SCORM shape. Prefer `/api/v1/sessions/{sessionId}`.","operationId":"getLegacyScormSession","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Legacy SCORM session","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"`WORKSPACE_ADMIN_REQUIRED` for a signed-in dashboard session that is not an active workspace owner or admin","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["SCORM"],"summary":"Update a SCORM session (legacy)","description":"Updates CMI data in the legacy SCORM shape. Prefer `/api/v1/sessions/{sessionId}`.","operationId":"updateLegacyScormSession","security":[{"BearerApiKey":[]},{"ApiKeyAuth":[]}],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"cmi_data":{"type":"object","additionalProperties":true},"completion_status":{"type":"string","enum":["not_attempted","incomplete","completed","passed","failed"]},"success_status":{"type":"string","enum":["unknown","passed","failed"]},"score":{"type":"object","properties":{"scaled":{"type":"number"},"raw":{"type":"number"}}},"session_time":{"type":"string"},"suspend_data":{"type":"string"}}}}}},"responses":{"200":{"description":"Updated session","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/v1/system/white-label-status":{"get":{"tags":["Tenants"],"summary":"Get white-label infrastructure readiness","description":"Read-only readiness probe for the white-label flow. Reports env-var configuration and whether the Vercel Domains API is believed to be usable. No authentication required.","operationId":"getWhiteLabelStatus","security":[],"responses":{"200":{"description":"White-label readiness","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/api/customer/tenant":{"get":{"tags":["Customer"],"summary":"Get current tenant overview","description":"Returns tenant summary, plan, and API key mode. Requires Clerk session.","operationId":"getCustomerTenant","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Tenant overview","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"307":{"description":"Redirect to onboarding"},"401":{"description":"Unauthorized (no Clerk session)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/tenant/switch":{"post":{"tags":["Customer"],"summary":"Switch active workspace","description":"Switches the session to a different workspace (subtenant). Requires Clerk session.","operationId":"switchCustomerWorkspace","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tenantId"],"properties":{"tenantId":{"type":"string"}}}}}},"responses":{"200":{"description":"Switch result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Workspace not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/packages":{"get":{"tags":["Customer"],"summary":"List packages for dashboard","description":"Returns dashboard package list for the active workspace. Requires Clerk session.","operationId":"listCustomerPackages","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Package list","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/packages/upload-limit-preflight":{"get":{"tags":["Customer"],"summary":"Check upload limit preflight","description":"Pre-checks upload eligibility against plan limits before starting an upload.","operationId":"customerUploadLimitPreflight","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Preflight result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/packages/{packageId}":{"get":{"tags":["Customer"],"summary":"Get a package (dashboard)","operationId":"getCustomerPackage","security":[{"ClerkSession":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Package detail","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["Customer"],"summary":"Delete / archive a package (dashboard)","operationId":"deleteCustomerPackage","security":[{"ClerkSession":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/packages/{packageId}/lifecycle":{"post":{"tags":["Customer"],"summary":"Manage package lifecycle (dashboard)","description":"Archive, restore, or otherwise change package lifecycle state.","operationId":"customerPackageLifecycle","security":[{"ClerkSession":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Lifecycle updated","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Lifecycle conflict; or `SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/packages/{packageId}/activity":{"get":{"tags":["Customer"],"summary":"Get package activity log (dashboard)","operationId":"getCustomerPackageActivity","security":[{"ClerkSession":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Activity events","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/packages/{packageId}/versions/{versionId}/activate":{"post":{"tags":["Customer"],"summary":"Activate a specific package version","operationId":"activatePackageVersion","security":[{"ClerkSession":[]}],"parameters":[{"name":"packageId","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}],"responses":{"200":{"description":"Version activated","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Package or version not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/dispatches":{"get":{"tags":["Customer"],"summary":"List dispatches (dashboard)","operationId":"listCustomerDispatches","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Dispatch list","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create a dispatch (dashboard)","operationId":"createCustomerDispatch","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Dispatch created","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error; or `SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Lifecycle conflict; or `SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/dispatches/{dispatchId}":{"get":{"tags":["Customer"],"summary":"Get a dispatch (dashboard)","operationId":"getCustomerDispatch","security":[{"ClerkSession":[]}],"parameters":[{"name":"dispatchId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Dispatch detail","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Dispatch not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"patch":{"tags":["Customer"],"summary":"Update a dispatch (dashboard)","operationId":"updateCustomerDispatch","security":[{"ClerkSession":[]}],"parameters":[{"name":"dispatchId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated dispatch","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Dispatch not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["Customer"],"summary":"Delete a dispatch (dashboard)","operationId":"deleteCustomerDispatch","security":[{"ClerkSession":[]}],"parameters":[{"name":"dispatchId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Dispatch not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/dispatches/{dispatchId}/activity":{"get":{"tags":["Customer"],"summary":"Get dispatch activity log (dashboard)","operationId":"getCustomerDispatchActivity","security":[{"ClerkSession":[]}],"parameters":[{"name":"dispatchId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Activity events","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/dispatches/{dispatchId}/zip":{"get":{"tags":["Customer"],"summary":"Download dispatch SCORM ZIP (dashboard)","operationId":"downloadCustomerDispatchZip","security":[{"ClerkSession":[]}],"parameters":[{"name":"dispatchId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"SCORM ZIP","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Dispatch not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/dispatches/lifecycle":{"post":{"tags":["Customer"],"summary":"Bulk dispatch lifecycle action (dashboard)","description":"Pause, resume, archive, restore, extend or delete up to 200 dispatches of one workspace. The whole request is one transaction, which finds every dispatch in the workspace before it changes any: it changes all of them or none, never some. A refusal means none was changed: `404 DISPATCH_NOT_FOUND`, `413 DISPATCH_LIFECYCLE_BATCH_TOO_LARGE`, `503 DISPATCH_LIFECYCLE_UNAVAILABLE`, the two workspace refusals, and `400 DISPATCH_LIFECYCLE_FAILED` with `outcome: \"unchanged\"`. `400 DISPATCH_LIFECYCLE_FAILED` with `outcome: \"unknown\"` is not a refusal: the answer from the transaction was lost or the backend failed, so the dispatches may all have been changed. Read them (`GET /api/customer/dispatches`) before sending the request again. The same holds when no answer arrives at all.","operationId":"customerDispatchLifecycle","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Lifecycle updated","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid payload (`INVALID_JSON`, `INVALID_REQUEST`); or `DISPATCH_LIFECYCLE_FAILED`, whose `outcome` is `\"unchanged\"` when the transaction refused and changed nothing, and `\"unknown\"` when its answer was lost: then all of the dispatches were changed or none was, and they must be read before the request is sent again; or `SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"`DISPATCH_NOT_FOUND`: one or more dispatches were not found in the workspace; none was changed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"413":{"description":"`DISPATCH_LIFECYCLE_BATCH_TOO_LARGE`: these dispatches hold more than one transaction can change; none was changed. Select fewer and try again.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"`DISPATCH_LIFECYCLE_UNAVAILABLE`: the backend does not have this operation yet (a release is in progress); none was changed. Try again shortly.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/organizations":{"get":{"tags":["Customer"],"summary":"List organizations (dashboard)","operationId":"listCustomerOrganizations","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Organizations","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create an organization (dashboard)","operationId":"createCustomerOrganization","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":120},"kind":{"type":"string","enum":["internal","external"],"default":"external"}}}}}},"responses":{"201":{"description":"Created organization","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error; or `SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/usage":{"get":{"tags":["Customer"],"summary":"Get usage overview (dashboard)","operationId":"getCustomerUsage","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Usage overview","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/billing":{"get":{"tags":["Customer"],"summary":"Get billing overview (dashboard)","operationId":"getCustomerBilling","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Billing overview","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/billing/portal":{"post":{"tags":["Customer"],"summary":"Create Stripe billing portal session","operationId":"createBillingPortalSession","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Billing portal URL","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"503":{"description":"Billing provider unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/billing/flexible-usage/opt-in":{"post":{"tags":["Customer"],"summary":"Opt in to flexible usage billing","operationId":"optInFlexibleUsage","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Opt-in result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/shell-state":{"get":{"tags":["Customer"],"summary":"Get shell notification state","description":"Single-request aggregation of everything the shell notification bell needs: usage overview, webhooks health, and integration incidents. Each section degrades independently.","operationId":"getCustomerShellState","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Shell state","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/activity":{"get":{"tags":["Customer"],"summary":"Get tenant activity log (dashboard)","operationId":"getCustomerActivity","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Activity events","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/api-keys/{apiKeyId}/activity":{"get":{"tags":["Customer"],"summary":"Get API key activity log (dashboard)","operationId":"getApiKeyActivity","security":[{"ClerkSession":[]}],"parameters":[{"name":"apiKeyId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Activity events","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/ask":{"post":{"tags":["Customer"],"summary":"Dashboard AI assistant query","operationId":"customerAsk","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"AI answer","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/contracts":{"get":{"tags":["Customer"],"summary":"Get customer contracts (dashboard)","operationId":"getCustomerContracts","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Contracts","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/compliance-settings":{"get":{"tags":["Customer"],"summary":"Get compliance settings","operationId":"getComplianceSettings","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Compliance settings","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Customer"],"summary":"Update compliance settings","operationId":"updateComplianceSettings","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated settings","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/connections/{connectionId}/activity":{"get":{"tags":["Customer"],"summary":"Get connection activity log","operationId":"getConnectionActivity","security":[{"ClerkSession":[]}],"parameters":[{"name":"connectionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Activity events","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/endpoints/activity":{"get":{"tags":["Customer"],"summary":"Get endpoint activity log","operationId":"getEndpointActivity","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Activity events","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/integration-incidents":{"get":{"tags":["Customer"],"summary":"List integration incidents","operationId":"listCustomerIntegrationIncidents","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Integration incidents","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/integration-incidents/{incidentId}":{"get":{"tags":["Customer"],"summary":"Get an integration incident","operationId":"getCustomerIntegrationIncident","security":[{"ClerkSession":[]}],"parameters":[{"name":"incidentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Integration incident detail","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Incident not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"patch":{"tags":["Customer"],"summary":"Acknowledge an integration incident","operationId":"acknowledgeCustomerIntegrationIncident","security":[{"ClerkSession":[]}],"parameters":[{"name":"incidentId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated incident","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Incident not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/invoices":{"get":{"tags":["Customer"],"summary":"List invoices (dashboard)","operationId":"listCustomerInvoices","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Invoices","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/privacy-requests":{"get":{"tags":["Customer"],"summary":"List privacy requests","operationId":"listPrivacyRequests","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Privacy requests","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create a privacy request","operationId":"createPrivacyRequest","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Created privacy request","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error; or `SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/privacy-requests/{requestId}":{"get":{"tags":["Customer"],"summary":"Get a privacy request","operationId":"getPrivacyRequest","security":[{"ClerkSession":[]}],"parameters":[{"name":"requestId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Privacy request","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/privacy-requests/{requestId}/erasure":{"post":{"tags":["Customer"],"summary":"Execute erasure for a privacy request","operationId":"executePrivacyErasure","security":[{"ClerkSession":[]}],"parameters":[{"name":"requestId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}],"responses":{"200":{"description":"Erasure executed","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Request not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"The declared learner reference is more than one learner in the SCORM 2004 learner store; repeat with acknowledge_learner_store_span set to the reported number; or `SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/privacy-requests/{requestId}/export":{"post":{"tags":["Customer"],"summary":"Export data for a privacy request","operationId":"exportPrivacyRequestData","security":[{"ClerkSession":[]}],"parameters":[{"name":"requestId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}],"responses":{"200":{"description":"Export initiated or data payload","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Request not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"The declared learner reference is more than one learner in the SCORM 2004 learner store; repeat with acknowledge_learner_store_span set to the reported number; or `SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/privacy-retention":{"get":{"tags":["Customer"],"summary":"Get privacy retention settings","operationId":"getPrivacyRetention","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Retention settings","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Customer"],"summary":"Update privacy retention settings","operationId":"updatePrivacyRetention","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/reports/custom":{"get":{"tags":["Customer"],"summary":"Get custom report data (dashboard)","description":"Accepts optional `?type` to select report kind.","operationId":"getCustomReport","security":[{"ClerkSession":[]}],"parameters":[{"name":"type","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Report data","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Run a custom report (dashboard)","operationId":"runCustomReport","security":[{"ClerkSession":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Report result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/reports/custom/export":{"get":{"tags":["Customer"],"summary":"Export custom report as CSV (dashboard)","operationId":"exportCustomReport","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"CSV download","content":{"text/csv":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/reports/learner-progress":{"get":{"tags":["Customer"],"summary":"Get learner progress report","operationId":"getLearnerProgressReport","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Learner progress report","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Run learner progress report with filters","operationId":"runLearnerProgressReport","security":[{"ClerkSession":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Report result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/reports/learner-progress/export":{"get":{"tags":["Customer"],"summary":"Export learner progress report as CSV","operationId":"exportLearnerProgressReport","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"CSV download","content":{"text/csv":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/reports/generate":{"post":{"tags":["Customer"],"summary":"Trigger report generation","operationId":"generateReport","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Generation result or download URL","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/reports/schedules":{"get":{"tags":["Customer"],"summary":"List report schedules","operationId":"listReportSchedules","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Report schedules","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create a report schedule","operationId":"createReportSchedule","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Created schedule","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/reports/audit-packet":{"get":{"tags":["Customer"],"summary":"Download audit packet","description":"Returns a signed audit evidence packet. Requires signing config to be present.","operationId":"getAuditPacket","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Audit packet","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Signing config not present","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Generate audit packet","operationId":"generateAuditPacket","security":[{"ClerkSession":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Audit packet","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Signing config not present","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/reports/evidence-packet":{"get":{"tags":["Customer"],"summary":"Get evidence packet","operationId":"getEvidencePacket","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Evidence packet","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/subtenants":{"get":{"tags":["Customer"],"summary":"List subtenants","operationId":"listSubtenants","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Subtenants","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create a subtenant","operationId":"createSubtenant","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Created subtenant","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error; or `SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/subtenants/{subtenantId}/status":{"get":{"tags":["Customer"],"summary":"Get subtenant status","operationId":"getSubtenantStatus","security":[{"ClerkSession":[]}],"parameters":[{"name":"subtenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Subtenant status","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Subtenant not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Customer"],"summary":"Update subtenant status","operationId":"updateSubtenantStatus","security":[{"ClerkSession":[]}],"parameters":[{"name":"subtenantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Subtenant not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/subtenants/{subtenantId}/api-keys":{"get":{"tags":["Customer"],"summary":"List child API keys for a subtenant","operationId":"listSubtenantApiKeys","security":[{"ClerkSession":[]}],"parameters":[{"name":"subtenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"API keys","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Subtenant not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create a child API key for a subtenant","operationId":"createSubtenantApiKey","security":[{"ClerkSession":[]}],"parameters":[{"name":"subtenantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Created API key","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/subtenants/{subtenantId}/domain":{"get":{"tags":["Customer"],"summary":"Get subtenant custom domain","operationId":"getSubtenantDomain","security":[{"ClerkSession":[]}],"parameters":[{"name":"subtenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Domain config","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Subtenant not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Customer"],"summary":"Set subtenant custom domain","operationId":"setSubtenantDomain","security":[{"ClerkSession":[]}],"parameters":[{"name":"subtenantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated domain","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Subtenant not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["Customer"],"summary":"Remove subtenant custom domain","operationId":"deleteSubtenantDomain","security":[{"ClerkSession":[]}],"parameters":[{"name":"subtenantId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Subtenant not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/webhooks":{"get":{"tags":["Customer"],"summary":"List webhook endpoints (dashboard)","operationId":"listCustomerWebhooks","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Webhook endpoints","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create a webhook endpoint (dashboard)","operationId":"createCustomerWebhook","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Created webhook","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error; or `SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/webhooks/{endpointId}":{"get":{"tags":["Customer"],"summary":"Get a webhook endpoint (dashboard)","operationId":"getCustomerWebhook","security":[{"ClerkSession":[]}],"parameters":[{"name":"endpointId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Webhook endpoint","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"patch":{"tags":["Customer"],"summary":"Update a webhook endpoint (dashboard)","operationId":"updateCustomerWebhook","security":[{"ClerkSession":[]}],"parameters":[{"name":"endpointId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"delete":{"tags":["Customer"],"summary":"Delete a webhook endpoint (dashboard)","operationId":"deleteCustomerWebhook","security":[{"ClerkSession":[]}],"parameters":[{"name":"endpointId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/webhooks/deliveries/{deliveryId}/retry":{"post":{"tags":["Customer"],"summary":"Retry a failed webhook delivery","operationId":"retryWebhookDelivery","security":[{"ClerkSession":[]}],"parameters":[{"name":"deliveryId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}],"responses":{"200":{"description":"Retry queued","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Delivery not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/webhooks/send-test":{"post":{"tags":["Customer"],"summary":"Send a test webhook event","operationId":"sendTestWebhook","security":[{"ClerkSession":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Test sent","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the address names no workspace and the request did not state one. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the address names no workspace and the request states one the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. Required unless the address names a workspace with `?workspace=` (older spelling `?tenantId=`); a request that names one is authorized in that workspace and this header is not read. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/xapi/statements":{"get":{"tags":["Customer"],"summary":"List xAPI statements (dashboard)","operationId":"listCustomerXapiStatements","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"xAPI statements","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/xapi/replay":{"post":{"tags":["Customer"],"summary":"Replay xAPI statements","operationId":"replayCustomerXapi","security":[{"ClerkSession":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Replay result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/competency/ask":{"post":{"tags":["Customer"],"summary":"Competency AI assistant query (dashboard)","operationId":"customerCompetencyAsk","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"AI answer","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/competency/ask/history":{"get":{"tags":["Customer"],"summary":"Get competency AI query history (dashboard)","operationId":"customerCompetencyAskHistory","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Query history","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/learners/{userId}/history":{"get":{"tags":["Customer"],"summary":"Get learner competency history (dashboard)","operationId":"customerLearnerCompetencyHistory","security":[{"ClerkSession":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Learner competency history","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/learners/{userId}/roles":{"get":{"tags":["Customer"],"summary":"Get learner role assignments (dashboard)","operationId":"customerLearnerRoles","security":[{"ClerkSession":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Role assignments","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/packages":{"get":{"tags":["Customer"],"summary":"List competency packages (dashboard)","operationId":"listCustomerCompetencyPackages","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Competency packages","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/revenue":{"get":{"tags":["Customer"],"summary":"Get competency revenue data (dashboard)","operationId":"getCustomerCompetencyRevenue","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Revenue data","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/review":{"get":{"tags":["Customer"],"summary":"Get competency review queue (dashboard)","operationId":"getCustomerCompetencyReview","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Review queue","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Submit competency review action (dashboard)","operationId":"submitCustomerCompetencyReview","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Review result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/competency/roles":{"get":{"tags":["Customer"],"summary":"List competency roles (dashboard)","operationId":"listCustomerCompetencyRoles","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Roles","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create a competency role (dashboard)","operationId":"createCustomerCompetencyRole","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Created role","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/competency/roles/{roleId}/requirements":{"get":{"tags":["Customer"],"summary":"Get competency role requirements (dashboard)","operationId":"getCustomerCompetencyRoleRequirements","security":[{"ClerkSession":[]}],"parameters":[{"name":"roleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Requirements","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Customer"],"summary":"Set competency role requirements (dashboard)","operationId":"setCustomerCompetencyRoleRequirements","security":[{"ClerkSession":[]}],"parameters":[{"name":"roleId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated requirements","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/role-templates":{"get":{"tags":["Customer"],"summary":"List competency role templates (dashboard)","operationId":"listCustomerCompetencyRoleTemplates","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Role templates","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/skills":{"get":{"tags":["Customer"],"summary":"List competency skills (dashboard)","operationId":"listCustomerCompetencySkills","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Skills","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Customer"],"summary":"Create a competency skill (dashboard)","operationId":"createCustomerCompetencySkill","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Created skill","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/competency/skills/{skillId}/links":{"get":{"tags":["Customer"],"summary":"Get what a skill is connected to (dashboard)","description":"One skill and its place in the skill map: the skill it sits under, the skills under it, what it needs first, what it unlocks and what it is related to. A skill in another workspace answers 404.","operationId":"getCustomerCompetencySkillLinks","security":[{"ClerkSession":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill links","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid skill ID","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Skill not found in this workspace","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/skills/{skillId}/parent":{"put":{"tags":["Customer"],"summary":"Set or clear a skill's parent (dashboard)","description":"Workspace owners and admins only. `\"parentId\": null` clears the parent. Refusals carry the same codes as `PUT /api/v1/capability/skills/{skillId}/parent`.","operationId":"setCustomerCompetencySkillParent","security":[{"ClerkSession":[]}],"parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["parentId"],"properties":{"parentId":{"type":["string","null"],"minLength":1,"maxLength":200}}}}}},"responses":{"200":{"description":"Parent result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request; or `SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Workspace owner or admin access required (SKILL_MAP_ADMIN_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Skill not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"The parent already sits under this skill (PARENT_CYCLE); or `SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"The parent cannot be used","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/customer/competency/skill-links":{"post":{"tags":["Customer"],"summary":"Link two skills (dashboard)","description":"Workspace owners and admins only. A `prerequisite` link points from the prerequisite (`fromSkillId`) to the skill it unlocks (`toSkillId`); a `related` link has no direction. Refusals carry the same codes as `POST /api/v1/capability/skill-links`.","operationId":"createCustomerCompetencySkillLink","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fromSkillId","toSkillId","type"],"properties":{"fromSkillId":{"type":"string","minLength":1,"maxLength":200},"toSkillId":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["prerequisite","related"]}}}}}},"responses":{"200":{"description":"The link already stood (`changed: false`)","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"201":{"description":"Link created","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request; or `SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Workspace owner or admin access required (SKILL_MAP_ADMIN_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Skill not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"Conflicts with the current map (PREREQUISITE_CYCLE, LINK_TYPE_CONFLICT); or `SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"422":{"description":"A skill cannot be linked","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]},"delete":{"tags":["Customer"],"summary":"Remove a link between two skills (dashboard)","description":"Workspace owners and admins only. Removes the link named in the JSON body; a link that is not there answers `changed: false`.","operationId":"removeCustomerCompetencySkillLink","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["fromSkillId","toSkillId","type"],"properties":{"fromSkillId":{"type":"string","minLength":1,"maxLength":200},"toSkillId":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["prerequisite","related"]}}}}}},"responses":{"200":{"description":"Removal result","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid request; or `SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Workspace owner or admin access required (SKILL_MAP_ADMIN_REQUIRED)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"404":{"description":"Skill not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/customer/competency/value-inputs":{"get":{"tags":["Customer"],"summary":"Get competency value model inputs (dashboard)","operationId":"getCustomerCompetencyValueInputs","security":[{"ClerkSession":[]}],"responses":{"200":{"description":"Value inputs","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"put":{"tags":["Customer"],"summary":"Update competency value model inputs (dashboard)","operationId":"updateCustomerCompetencyValueInputs","security":[{"ClerkSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`SESSION_WORKSPACE_REQUIRED`: the request did not state the workspace its page was rendered for. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"409":{"description":"`SESSION_WORKSPACE_CHANGED`: the request states a workspace the session is not using. Nothing was changed.","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"parameters":[{"name":"X-Connect-Session-Workspace","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"The workspace the page that sent this request was rendered for. It is compared with the workspace the session is using and never selects or authorizes one."}]}},"/api/admin/tenants":{"get":{"tags":["Admin"],"summary":"List all tenants (admin)","description":"Returns the admin tenant table with metrics. Requires platform_admin role.","operationId":"adminListTenants","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Tenant list with metrics","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden (platform_admin required)","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/metrics/usage":{"get":{"tags":["Admin"],"summary":"Get platform usage metrics (admin)","operationId":"adminGetUsageMetrics","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Usage metrics","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/provision-enterprise":{"post":{"tags":["Admin"],"summary":"Provision an enterprise tenant (admin)","description":"Creates a Clerk user and provisions a new tenant. In-memory rate-limited per admin.","operationId":"adminProvisionEnterprise","security":[{"AdminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Provisioned tenant","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"429":{"description":"Admin rate limit exceeded","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/audit-logs":{"get":{"tags":["Admin"],"summary":"Get platform audit logs (admin)","operationId":"adminGetAuditLogs","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Audit logs","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/funnel":{"get":{"tags":["Admin"],"summary":"Get GTM funnel scorecard (admin)","operationId":"adminGetFunnel","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Funnel scorecard","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Admin"],"summary":"Record GTM funnel event or set baseline (admin)","description":"Action: `log_event` records a founder-led CRM event; `set_baseline` records per-stage baselines.","operationId":"adminPostFunnelEvent","security":[{"AdminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Event recorded","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/packages":{"get":{"tags":["Admin"],"summary":"List all packages across tenants (admin)","operationId":"adminListPackages","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Packages","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/webhooks":{"get":{"tags":["Admin"],"summary":"List all webhook endpoints across tenants (admin)","operationId":"adminListWebhooks","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Webhook endpoints","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/integration-incidents":{"get":{"tags":["Admin"],"summary":"List integration incidents across tenants (admin)","operationId":"adminListIntegrationIncidents","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Integration incidents","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}},"post":{"tags":["Admin"],"summary":"Create an integration incident (admin)","operationId":"adminCreateIntegrationIncident","security":[{"AdminSession":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/integration-incidents/outbox":{"get":{"tags":["Admin"],"summary":"Get integration incident outbox (admin)","operationId":"adminGetIntegrationIncidentOutbox","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Outbox","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/contracts":{"get":{"tags":["Admin"],"summary":"Get admin contract manifest (admin)","operationId":"adminGetContracts","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Admin contracts","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}},"/api/admin/live-activity/proof":{"get":{"tags":["Admin"],"summary":"Get live activity proof (admin)","operationId":"adminGetLiveActivityProof","security":[{"AdminSession":[]}],"responses":{"200":{"description":"Live activity proof","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human readable error message"},"code":{"type":"string","description":"Stable machine readable error code"},"details":{"description":"Additional context for debugging"},"retryable":{"type":"boolean","description":"True when the same request may be retried after the Retry-After delay"},"current_version":{"type":"integer","description":"Present on 409 VERSION_CONFLICT — latest session revision to retry against"},"message":{"type":"string","description":"Optional remediation hint for recoverable errors such as VERSION_CONFLICT"}},"examples":{"missingApiKey":{"value":{"error":"Missing API key","code":"API_KEY_REQUIRED","details":{"accepted_headers":["Authorization: Bearer <api_key>","X-API-Key: <api_key>"]}}},"invalidApiKey":{"value":{"error":"A valid API key with an allowed scope and matching mode is required","code":"API_KEY_REQUIRED","details":{"reasons":["invalid","revoked","wrong_mode","scope_not_allowed"]}}},"versionConflict":{"value":{"error":"Version conflict detected. Another update was made to this session before your commit completed.","code":"VERSION_CONFLICT","current_version":5,"message":"Fetch the latest session payload and retry the commit."}},"rateLimitExceeded":{"value":{"error":"Rate limit exceeded","code":"RATE_LIMIT_EXCEEDED","details":{"limit":100,"window":"60 seconds","retry_after":30}}},"validationError":{"value":{"error":"Validation error","code":"VALIDATION_ERROR","details":{"field":"user_id","message":"user_id is required"}}},"notFound":{"value":{"error":"Package not found","code":"NOT_FOUND","details":{"resource":"package","id":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}}}}}}