{"openapi":"3.0.0","paths":{"/v1/configs/{sdk_key}/config.json":{"get":{"description":"The config JSON (schema 1) every SDK downloads and evaluates locally: no user data is sent. Authenticated by the SDK key in the path, which can read only this config in this environment; no API key or session. Poll with `If-None-Match` (the last `ETag`) and get 304 while nothing changed; changes show within about 5 seconds. Responses are `br`, `gzip` or identity per `Accept-Encoding`, CORS `*` without credentials. Limits: 20 requests per second per (SDK key, client IP) and 20 per client IP; a matching 304 is never refused for the key's sake; unknown keys 2 per second per IP. If the database is unreachable the API keeps serving its last good copy with `X-PC-Config-Stale: 1` for up to 24 hours. `HEAD` answers the same headers without the body.","operationId":"DeliveryController_get","parameters":[{"name":"sdk_key","required":true,"in":"path","schema":{"type":"string","pattern":"^pcf_sdk_[0-9A-Za-z]{38}$"},"description":"The SDK key of one config in one environment (`pcf_sdk_` + 38 characters). A malformed key or a wrong checksum is a 404."}],"responses":{"200":{"description":"The config JSON document (schema 1, no envelope).","headers":{"ETag":{"description":"Weak ETag of the config (`W/\"…\"`), the same for every content coding. Send it back as `If-None-Match`.","schema":{"type":"string"}},"X-PC-Config-Revision":{"description":"The config revision (monotonic within a generation).","schema":{"type":"integer"}},"X-PC-Config-Generation":{"description":"The config generation; a new generation resets the SDK revision guard.","schema":{"type":"integer"}},"X-PC-Config-Stale":{"description":"Present (`1`) when the API serves its last good copy because its database is unreachable (at most 24 hours).","schema":{"type":"string","enum":["1"]}},"Cache-Control":{"description":"`public, max-age=0, s-maxage=15, stale-while-revalidate=15, stale-if-error=3600`.","schema":{"type":"string"}},"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"304":{"description":"Not modified: `If-None-Match` matches the current config.","headers":{"ETag":{"description":"Weak ETag of the config (`W/\"…\"`), the same for every content coding. Send it back as `If-None-Match`.","schema":{"type":"string"}},"X-PC-Config-Revision":{"description":"The config revision (monotonic within a generation).","schema":{"type":"integer"}},"X-PC-Config-Generation":{"description":"The config generation; a new generation resets the SDK revision guard.","schema":{"type":"integer"}},"X-PC-Config-Stale":{"description":"Present (`1`) when the API serves its last good copy because its database is unreachable (at most 24 hours).","schema":{"type":"string","enum":["1"]}},"Cache-Control":{"description":"`public, max-age=0, s-maxage=15, stale-while-revalidate=15, stale-if-error=3600`.","schema":{"type":"string"}},"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"404":{"description":"`SDK_KEY_NOT_FOUND`: the key is malformed, unknown, revoked, an expired secondary key, or its workspace is suspended or deleted.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SDK_KEY_NOT_FOUND"]},"429":{"description":"`RATE_LIMITED`: over the per-IP or per-(key, IP) limit, or too many unknown keys; honour `Retry-After`. Per-IP limit: more than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]},"503":{"description":"`SERVICE_UNAVAILABLE`: the database is unreachable and this pod holds no copy of the config; keep your last config and retry.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["SERVICE_UNAVAILABLE"]}},"security":[],"summary":"Download a config","tags":["Delivery"],"x-pc-sdk":false}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/revisions":{"get":{"description":"Published revisions of the config in one environment, newest first. Every write that changes what SDKs download publishes a revision; edits that do not (a description, a name) do not. The last 100 revisions, or 20 MiB of compressed snapshots, are kept, and the current one always.","operationId":"RevisionsController_list","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor for pagination: the `next_cursor` of the previous page.","schema":{"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ","type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":50,"type":"integer"},"example":50},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"A page of revisions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigRevisionListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a bad cursor or `limit`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`: no such config in this workspace, or the environment is not one of its project.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List config revisions","tags":["revisions"],"x-pc-sdk":{"resource":"configs.environments.revisions","method":"list","bind":["workspace_id"],"paginated":true}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/revisions/{revision}":{"get":{"description":"The config JSON (schema 1) of one revision, byte for byte what SDKs download: keys, types, values, rules, segments and hashes, but no names, descriptions or cleartext of confidential lists. The response body is the document itself (no envelope).","operationId":"RevisionsController_get","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"revision","required":true,"in":"path","schema":{"type":"integer","minimum":1},"description":"The revision number.","example":1},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The config JSON document (schema 1). `ETag` carries the revision's ETag.","headers":{"ETag":{"description":"The revision's ETag, quoted.","schema":{"type":"string"}},"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"`VALIDATION_ERROR`: `revision` is not a positive integer.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`: no such config in this workspace, or the environment is not one of its project. `REVISION_NOT_FOUND`: no such revision (never published, or pruned).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND","REVISION_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get a config revision","tags":["revisions"],"x-pc-sdk":{"resource":"configs.environments.revisions","method":"retrieve","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/projects":{"get":{"description":"The workspace's projects, oldest first, each with its environments and configs.","operationId":"ProjectsController_list","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor for pagination: the `next_cursor` of the previous page.","schema":{"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ","type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":50,"type":"integer"},"example":50}],"responses":{"200":{"description":"A page of projects.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a bad cursor or a `limit` outside 1-100.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List projects","tags":["projects"],"x-pc-sdk":{"resource":"projects","method":"list","bind":["workspace_id"],"paginated":true}},"post":{"description":"Creates the project with the environments of `environment_preset` (default `dev_prod`: Development and a protected Production) and one config, `main`, unless you pass `environments` / `configs`. Every config gets a published state in every environment. Needs `flags.project.manage`.","operationId":"ProjectsController_create","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Idempotency key (1-256 characters, `[A-Za-z0-9_-:]`). A retry with the same key and body returns the first response for 24 h.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectDto"}}}},"responses":{"201":{"description":"The new project, with its environments and configs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is missing or invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"409":{"description":"`KEY_ALREADY_EXISTS`: another project has this name, or a key repeats in `environments` / `configs`. Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"`LIMIT_EXCEEDED`: the workspace already has the maximum number of projects (`details`: `limit`, `max`, `current`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","LIMIT_EXCEEDED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Create a project","tags":["projects"],"x-pc-sdk":{"resource":"projects","method":"create","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/projects/{project_id}":{"get":{"description":"The project with its environments and configs.","operationId":"ProjectsController_get","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The project.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get a project","tags":["projects"],"x-pc-sdk":{"resource":"projects","method":"retrieve","bind":["workspace_id"],"paginated":false}},"patch":{"description":"Rename, describe or reorder the project. Only the fields you send change. Needs `flags.project.manage`.","operationId":"ProjectsController_update","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectDto"}}}},"responses":{"200":{"description":"The updated project.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: another project has this name.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Update a project","tags":["projects"],"x-pc-sdk":{"resource":"projects","method":"update","bind":["workspace_id"],"paginated":false}},"delete":{"description":"Deletes the project with all of its environments, configs, flags, segments, SDK keys and history. Pass `confirm` with the exact project name. SDKs using its keys stop receiving updates. Needs `flags.project.manage`; recorded in the workspace audit log.","operationId":"ProjectsController_delete","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"note","required":false,"in":"query","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","schema":{"maxLength":500,"example":"Ticket FLAG-142","type":"string"},"example":"Ticket FLAG-142"},{"name":"confirm","required":true,"in":"query","description":"The project's exact name, to confirm the delete. Deleting a project deletes its environments, configs, flags, segments, SDK keys and history.","schema":{"example":"Storefront","type":"string"},"example":"Storefront"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"204":{"description":"Deleted.","headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"422":{"description":"`CONFIRMATION_REQUIRED`: `confirm` is missing or is not the exact project name.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","CONFIRMATION_REQUIRED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Delete a project","tags":["projects"],"x-pc-sdk":{"resource":"projects","method":"delete","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/limits":{"get":{"description":"The preview limits that apply to this workspace and how much of the counted ones it uses.","operationId":"LimitsController_get","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"Limits and usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagsLimitsResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get Flags limits and usage","tags":["limits"],"x-pc-sdk":{"resource":"limits","method":"retrieve","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/projects/{project_id}/environments":{"get":{"description":"Every environment of the project, in `ordinal` order.","operationId":"EnvironmentsController_list","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The environments.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List environments","tags":["environments"],"x-pc-sdk":{"resource":"projects.environments","method":"list","bind":["workspace_id"],"paginated":false}},"post":{"description":"Adds an environment to every config of the project. The key `production` starts protected unless you say otherwise. Needs `flags.project.manage`.","operationId":"EnvironmentsController_create","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Idempotency key (1-256 characters, `[A-Za-z0-9_-:]`). A retry with the same key and body returns the first response for 24 h.","required":false,"schema":{"type":"string"}},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnvironmentDto"}}}},"responses":{"201":{"description":"The new environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is missing or invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: the project already has an environment with this key. Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"`LIMIT_EXCEEDED`: the project already has the maximum number of environments (`details`: `limit`, `max`, `current`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","LIMIT_EXCEEDED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Create an environment","tags":["environments"],"x-pc-sdk":{"resource":"projects.environments","method":"create","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/projects/{project_id}/environments/{environment_id}":{"get":{"operationId":"EnvironmentsController_get","parameters":[{"name":"environment_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the environment.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`ENVIRONMENT_NOT_FOUND`: no such environment in this project.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get an environment","tags":["environments"],"x-pc-sdk":{"resource":"projects.environments","method":"retrieve","bind":["workspace_id"],"paginated":false}},"patch":{"description":"Name, color, order, `protected` and `require_note`; the key never changes. Changing `protected` or `require_note` is recorded in the workspace audit log. Needs `flags.project.manage`.","operationId":"EnvironmentsController_update","parameters":[{"name":"environment_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the environment.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentDto"}}}},"responses":{"200":{"description":"The updated environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`ENVIRONMENT_NOT_FOUND`: no such environment in this project.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Update an environment","tags":["environments"],"x-pc-sdk":{"resource":"projects.environments","method":"update","bind":["workspace_id"],"paginated":false}},"delete":{"description":"Deletes the environment with its values in every config, and its SDK keys. A project keeps at least one environment. Needs `flags.project.manage`.","operationId":"EnvironmentsController_delete","parameters":[{"name":"environment_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the environment.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"note","required":false,"in":"query","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","schema":{"maxLength":500,"example":"Ticket FLAG-142","type":"string"},"example":"Ticket FLAG-142"},{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"204":{"description":"Deleted.","headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`ENVIRONMENT_NOT_FOUND`: no such environment in this project.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"409":{"description":"`LAST_ENVIRONMENT`: this is the project's only environment.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","LAST_ENVIRONMENT"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Delete an environment","tags":["environments"],"x-pc-sdk":{"resource":"projects.environments","method":"delete","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/projects/{project_id}/configs":{"get":{"description":"The project's configs, in `ordinal` order.","operationId":"ProjectConfigsController_list","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor for pagination: the `next_cursor` of the previous page.","schema":{"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ","type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":50,"type":"integer"},"example":50},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"A page of configs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a bad cursor or a `limit` outside 1-100.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List configs","tags":["configs"],"x-pc-sdk":{"resource":"projects.configs","method":"list","bind":["workspace_id"],"paginated":true}},"post":{"description":"Adds a config to the project, with a published state in every environment. Each (config, environment) pair has its own SDK key. Needs `flags.project.manage`.","operationId":"ProjectConfigsController_create","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Idempotency key (1-256 characters, `[A-Za-z0-9_-:]`). A retry with the same key and body returns the first response for 24 h.","required":false,"schema":{"type":"string"}},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConfigDto"}}}},"responses":{"201":{"description":"The new config.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is missing or invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: the project already has a config with this key. Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"`LIMIT_EXCEEDED`: the project already has the maximum number of configs (`details`: `limit`, `max`, `current`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","LIMIT_EXCEEDED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Create a config","tags":["configs"],"x-pc-sdk":{"resource":"projects.configs","method":"create","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}":{"get":{"operationId":"ConfigsController_get","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The config.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND`: no such config in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get a config","tags":["configs"],"x-pc-sdk":{"resource":"configs","method":"retrieve","bind":["workspace_id"],"paginated":false}},"patch":{"description":"Key, name, description or order. Only the fields you send change. Needs `flags.project.manage`.","operationId":"ConfigsController_update","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConfigDto"}}}},"responses":{"200":{"description":"The updated config.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND`: no such config in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: the project already has a config with this key.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Update a config","tags":["configs"],"x-pc-sdk":{"resource":"configs","method":"update","bind":["workspace_id"],"paginated":false}},"delete":{"description":"Deletes the config with its flags, values and SDK keys in every environment. Needs `flags.project.manage`.","operationId":"ConfigsController_delete","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"note","required":false,"in":"query","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","schema":{"maxLength":500,"example":"Ticket FLAG-142","type":"string"},"example":"Ticket FLAG-142"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"204":{"description":"Deleted.","headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND`: no such config in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Delete a config","tags":["configs"],"x-pc-sdk":{"resource":"configs","method":"delete","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/projects/{project_id}/segments":{"get":{"description":"The project's segments, oldest first, with `usage_count`.","operationId":"ProjectSegmentsController_list","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor for pagination: the `next_cursor` of the previous page.","schema":{"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ","type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":50,"type":"integer"},"example":50},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"A page of segments.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a bad cursor or `limit`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List segments","tags":["segments"],"x-pc-sdk":{"resource":"projects.segments","method":"list","bind":["workspace_id"],"paginated":true}},"post":{"description":"A reusable set of ANDed user conditions that any config of the project can target with `{segment: {segment_id, comparator: in | not_in}}`. Confidential lists are stored as hashes plus encrypted cleartext; the response shows only their count.","operationId":"ProjectSegmentsController_create","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Idempotency key (1-256 characters, `[A-Za-z0-9_-:]`). A retry with the same key and body returns the first response for 24 h.","required":false,"schema":{"type":"string"}},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSegmentDto"}}}},"responses":{"201":{"description":"The new segment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentDetailResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is missing or invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: the project already has a segment with this key. Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"The conditions are invalid; `details.errors` lists every problem (`param`, `code`, `message`) and `code` is the first one: `INVALID_TARGETING` (shape, comparator or value), `LIMIT_EXCEEDED` (conditions, values or segments per project), `CONFIDENTIAL_LIST_NOT_EDITABLE` (`values_add` / `values_remove` on a list sent pre-hashed), or `NOTE_REQUIRED` (the segment is used in an environment that requires a `note`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","INVALID_TARGETING","LIMIT_EXCEEDED","CONFIDENTIAL_LIST_NOT_EDITABLE","NOTE_REQUIRED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Create a segment","tags":["segments"],"x-pc-sdk":{"resource":"projects.segments","method":"create","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/segments/{segment_id}":{"get":{"description":"The segment with its conditions and every (setting, environment) that uses it (`used_by`).","operationId":"SegmentsController_get","parameters":[{"name":"segment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the segment.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The segment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentDetailResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SEGMENT_NOT_FOUND`: no such segment in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SEGMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get a segment","tags":["segments"],"x-pc-sdk":{"resource":"segments","method":"retrieve","bind":["workspace_id"],"paginated":false}},"patch":{"description":"Key, name, description or conditions; only the fields you send change. Edit a confidential list with `list_id` plus `values_add` / `values_remove`. A segment used in a protected environment also needs `flags.protected.update` there.","operationId":"SegmentsController_update","parameters":[{"name":"segment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the segment.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSegmentDto"}}}},"responses":{"200":{"description":"The updated segment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentDetailResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`). A segment used in a protected environment also needs `flags.protected.update` on it.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SEGMENT_NOT_FOUND`: no such segment in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SEGMENT_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: the project already has a segment with this key; `VERSION_CONFLICT`: `version` is stale (`details.current_version`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS","VERSION_CONFLICT"]},"422":{"description":"The conditions are invalid; `details.errors` lists every problem (`param`, `code`, `message`) and `code` is the first one: `INVALID_TARGETING` (shape, comparator or value), `LIMIT_EXCEEDED` (conditions, values or segments per project), `CONFIDENTIAL_LIST_NOT_EDITABLE` (`values_add` / `values_remove` on a list sent pre-hashed), or `NOTE_REQUIRED` (the segment is used in an environment that requires a `note`). Publishing (every config that uses the segment): `CONFIG_TOO_LARGE` (a rendered config would exceed 1 MiB) or `LIMIT_EXCEEDED` with `details.limit: comparison_values_per_config`; the edit is not applied.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","INVALID_TARGETING","LIMIT_EXCEEDED","CONFIDENTIAL_LIST_NOT_EDITABLE","NOTE_REQUIRED","CONFIG_TOO_LARGE"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Update a segment","tags":["segments"],"x-pc-sdk":{"resource":"segments","method":"update","bind":["workspace_id"],"paginated":false}},"delete":{"description":"Deletes an unused segment. Needs `flags.delete`.","operationId":"SegmentsController_delete","parameters":[{"name":"segment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the segment.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"note","required":false,"in":"query","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","schema":{"maxLength":500,"example":"Ticket FLAG-142","type":"string"},"example":"Ticket FLAG-142"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"204":{"description":"Deleted.","headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SEGMENT_NOT_FOUND`: no such segment in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SEGMENT_NOT_FOUND"]},"409":{"description":"`SEGMENT_IN_USE`: a rule uses it (`details.used_by` lists where).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","SEGMENT_IN_USE"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Delete a segment","tags":["segments"],"x-pc-sdk":{"resource":"segments","method":"delete","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/segments/{segment_id}/confidential":{"get":{"description":"The cleartext of the segment's confidential lists, decrypted. Needs `flags.confidential.read`; every call is recorded in the history (`confidential.revealed`). Never cached.","operationId":"SegmentsController_reveal","parameters":[{"name":"segment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the segment.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The confidential lists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfidentialRevealResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SEGMENT_NOT_FOUND`: no such segment in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SEGMENT_NOT_FOUND"]},"422":{"description":"`CONFIDENTIAL_LIST_NOT_EDITABLE`: every confidential list was sent pre-hashed, so there is no cleartext.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","CONFIDENTIAL_LIST_NOT_EDITABLE"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Reveal confidential values of a segment","tags":["segments"],"x-pc-sdk":{"resource":"segments","method":"revealConfidential","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/settings":{"get":{"description":"The config's feature flags and settings, in `ordinal` order, with filters.","operationId":"ConfigSettingsController_list","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor for pagination: the `next_cursor` of the previous page.","schema":{"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ","type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":50,"type":"integer"},"example":50},{"name":"tag","required":false,"in":"query","description":"Only settings with this tag.","schema":{"example":"checkout","type":"string"},"example":"checkout"},{"name":"type","required":false,"in":"query","description":"Only settings of this type.","schema":{"$ref":"#/components/schemas/FlagsSettingType"},"example":"boolean"},{"name":"q","required":false,"in":"query","description":"Case-insensitive substring of the key or name.","schema":{"example":"checkout","type":"string"},"example":"checkout"},{"name":"lifecycle","required":false,"in":"query","description":"Only settings with this lifecycle.","schema":{"$ref":"#/components/schemas/FlagsSettingLifecycle"},"example":"temporary"},{"name":"owner_id","required":false,"in":"query","description":"Only settings owned by this user.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"A page of settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a bad filter, cursor or `limit`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND`: no such config in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List settings","tags":["settings"],"x-pc-sdk":{"resource":"configs.settings","method":"list","bind":["workspace_id"],"paginated":true}},"post":{"description":"Adds a feature flag (`boolean`) or a typed setting to the config, with a value in every environment (`initial_value`, else the type's zero). Needs `flags.create`; a non-zero `initial_value` is also a value write in every environment (protected ones need `flags.protected.update`).","operationId":"ConfigSettingsController_create","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Idempotency key (1-256 characters, `[A-Za-z0-9_-:]`). A retry with the same key and body returns the first response for 24 h.","required":false,"schema":{"type":"string"}},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSettingDto"}}}},"responses":{"201":{"description":"The new setting with its values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingDetailResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is missing or invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND`: no such config in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: the config already has a setting with this key. Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"`INVALID_VALUE`: `initial_value` does not match the type; `LIMIT_EXCEEDED`: the config has the maximum number of settings; `OWNER_NOT_A_MEMBER`: `owner_id` is not a workspace member; `NOTE_REQUIRED`. Publishing: `CONFIG_TOO_LARGE` (the rendered config would exceed 1 MiB; `details.size_bytes`, `max_bytes`) or `LIMIT_EXCEEDED` with `details.limit: comparison_values_per_config` (over 20,000 comparison values in the config); the write is not applied.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","INVALID_VALUE","LIMIT_EXCEEDED","OWNER_NOT_A_MEMBER","NOTE_REQUIRED","CONFIG_TOO_LARGE"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]},"503":{"description":"`SERVICE_UNAVAILABLE`: the member lookup for `owner_id` is unavailable; retry.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["SERVICE_UNAVAILABLE"]}},"security":[{"bearer":[]}],"summary":"Create a setting","tags":["settings"],"x-pc-sdk":{"resource":"configs.settings","method":"create","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/values":{"get":{"description":"Every setting of the config with its value and targeting in one environment (the flag list), in `ordinal` order. `include=states` adds each setting's compact state in every environment.","operationId":"ConfigSettingsController_listValues","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor for pagination: the `next_cursor` of the previous page.","schema":{"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ","type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":50,"type":"integer"},"example":50},{"name":"include","required":false,"in":"query","description":"`states` adds each setting's compact state in every environment of the project.","schema":{"enum":["states"],"type":"string"},"example":"states"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"A page of settings with their values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentValueListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a bad cursor, `limit` or `include`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND` (not an environment of the config's project).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List values in an environment","tags":["settings"],"x-pc-sdk":{"resource":"configs.environments.values","method":"list","bind":["workspace_id"],"paginated":true}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/compare":{"get":{"description":"Each setting's value and targeting side by side in 2-5 environments, with `differs` per setting.","operationId":"ConfigSettingsController_compare","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor for pagination: the `next_cursor` of the previous page.","schema":{"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ","type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":50,"type":"integer"},"example":50},{"name":"environment_ids","required":true,"in":"query","description":"Comma-separated environment ids of the config's project, 2-5 of them.","schema":{"example":"0b8c7a52-5a8e-4b8f-9d0a-6b1f0e0c1a11,7c1d9e44-2f3a-4c55-8e6b-1a2b3c4d5e6f","type":"string"},"example":"0b8c7a52-5a8e-4b8f-9d0a-6b1f0e0c1a11,7c1d9e44-2f3a-4c55-8e6b-1a2b3c4d5e6f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"A page of settings compared.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompareResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: `environment_ids` is not 2-5 environment ids.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Compare environments","tags":["settings"],"x-pc-sdk":{"resource":"configs","method":"compare","bind":["workspace_id"],"paginated":true}}},"/v1/workspaces/{workspace_id}/settings/{setting_id}":{"get":{"description":"The setting with its value and targeting in every environment, and what depends on it (`dependents`).","operationId":"SettingsController_get","parameters":[{"name":"setting_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the setting.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The setting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingDetailResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SETTING_NOT_FOUND`: no such setting in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SETTING_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get a setting","tags":["settings"],"x-pc-sdk":{"resource":"settings","method":"retrieve","bind":["workspace_id"],"paginated":false}},"patch":{"description":"Key, name, description, hint, tags, lifecycle, owner or order; only the fields you send change. The type cannot change. Renaming the key keeps the seed (users stay in their split buckets) and needs `flags.protected.update` when the project has a protected environment.","operationId":"SettingsController_update","parameters":[{"name":"setting_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the setting.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSettingDto"}}}},"responses":{"200":{"description":"The updated setting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingDetailResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SETTING_NOT_FOUND`: no such setting in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SETTING_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: the config already has a setting with this key.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS"]},"422":{"description":"`SETTING_TYPE_IMMUTABLE`: `type` differs from the current one; `OWNER_NOT_A_MEMBER`: `owner_id` is not a workspace member. Publishing: `CONFIG_TOO_LARGE` (the rendered config would exceed 1 MiB; `details.size_bytes`, `max_bytes`) or `LIMIT_EXCEEDED` with `details.limit: comparison_values_per_config` (over 20,000 comparison values in the config); the write is not applied.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","SETTING_TYPE_IMMUTABLE","OWNER_NOT_A_MEMBER","CONFIG_TOO_LARGE","LIMIT_EXCEEDED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]},"503":{"description":"`SERVICE_UNAVAILABLE`: the member lookup for `owner_id` is unavailable; retry.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["SERVICE_UNAVAILABLE"]}},"security":[{"bearer":[]}],"summary":"Update a setting","tags":["settings"],"x-pc-sdk":{"resource":"settings","method":"update","bind":["workspace_id"],"paginated":false}},"delete":{"description":"Deletes the setting and its values in every environment. Needs `flags.delete`.","operationId":"SettingsController_delete","parameters":[{"name":"setting_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the setting.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"note","required":false,"in":"query","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","schema":{"maxLength":500,"example":"Ticket FLAG-142","type":"string"},"example":"Ticket FLAG-142"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"204":{"description":"Deleted.","headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SETTING_NOT_FOUND`: no such setting in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SETTING_NOT_FOUND"]},"409":{"description":"`SETTING_IN_USE`: another setting uses it as a prerequisite (`details.used_by`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","SETTING_IN_USE"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Delete a setting","tags":["settings"],"x-pc-sdk":{"resource":"settings","method":"delete","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/settings/{setting_id}/values/{environment_id}":{"get":{"description":"The setting's value and targeting in one environment, with its `version`.","operationId":"SettingsController_getValue","parameters":[{"name":"setting_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the setting.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingValueResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SETTING_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SETTING_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get a value","tags":["settings"],"x-pc-sdk":{"resource":"settings.values","method":"retrieve","bind":["workspace_id"],"paginated":false}},"put":{"description":"Replaces the value and the whole targeting (rules, flag-level split, split attribute) in one environment. Send the `version` you read.","operationId":"SettingsController_putValue","parameters":[{"name":"setting_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the setting.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutSettingValueDto"}}}},"responses":{"200":{"description":"The new value.","headers":{"X-PC-Config-Size":{"description":"Size in bytes of this environment's published config JSON after the write (uncompressed). The maximum is 1 MiB (1,048,576); the console warns from 256 KB.","schema":{"type":"integer"}},"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingValueResponseDto"}}}},"400":{"description":"`VALIDATION_ERROR`: `version` or `note` is missing or invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`). Value writes need `flags.value.update` on the environment and the setting, plus `flags.protected.update` in a protected environment.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SETTING_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SETTING_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"409":{"description":"`VERSION_CONFLICT`: the value changed since you read it (`details.current_version`, `updated_at`, `updated_by`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","VERSION_CONFLICT"]},"422":{"description":"The value or targeting is invalid; `details.errors` lists every problem (`param`, `code`, `message`) and `code` is the first one: `INVALID_VALUE` (type mismatch, over 100 KB, json that does not parse), `INVALID_TARGETING` (shape, comparator or comparison value), `SEGMENT_NOT_FOUND` (a segment condition names no segment of this project), `CONFIDENTIAL_LIST_NOT_EDITABLE` (`values_add` / `values_remove` on a list sent pre-hashed), `PERCENTAGES_MUST_SUM_TO_100`, `PREREQUISITE_NOT_FOUND`, `PREREQUISITE_TYPE_MISMATCH`, `CIRCULAR_PREREQUISITE` (`details.cycle` lists the keys), `LIMIT_EXCEEDED` (rules, conditions, values or prerequisite depth), or `NOTE_REQUIRED` (the environment requires a `note`). Publishing: `CONFIG_TOO_LARGE` (the rendered config would exceed 1 MiB; `details.size_bytes`, `max_bytes`) or `LIMIT_EXCEEDED` with `details.limit: comparison_values_per_config` (over 20,000 comparison values in the config); the write is not applied.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","INVALID_VALUE","INVALID_TARGETING","SEGMENT_NOT_FOUND","CONFIDENTIAL_LIST_NOT_EDITABLE","PERCENTAGES_MUST_SUM_TO_100","PREREQUISITE_NOT_FOUND","PREREQUISITE_TYPE_MISMATCH","CIRCULAR_PREREQUISITE","LIMIT_EXCEEDED","NOTE_REQUIRED","CONFIG_TOO_LARGE"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Replace a value","tags":["settings"],"x-pc-sdk":{"resource":"settings.values","method":"replace","bind":["workspace_id"],"paginated":false}},"patch":{"description":"The quick edits: `value` (the toggle), `percentage_attribute`, and `clear_rules: true` to drop every rule and split so `value` is served to everyone (the kill switch). Send the `version` you read.","operationId":"SettingsController_patchValue","parameters":[{"name":"setting_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the setting.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSettingValueDto"}}}},"responses":{"200":{"description":"The new value.","headers":{"X-PC-Config-Size":{"description":"Size in bytes of this environment's published config JSON after the write (uncompressed). The maximum is 1 MiB (1,048,576); the console warns from 256 KB.","schema":{"type":"integer"}},"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingValueResponseDto"}}}},"400":{"description":"`VALIDATION_ERROR`: nothing to change, or `version` is missing.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`). Value writes need `flags.value.update` on the environment and the setting, plus `flags.protected.update` in a protected environment.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SETTING_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SETTING_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"409":{"description":"`VERSION_CONFLICT`: the value changed since you read it (`details.current_version`, `updated_at`, `updated_by`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","VERSION_CONFLICT"]},"422":{"description":"`INVALID_VALUE`, `INVALID_TARGETING` or `NOTE_REQUIRED`; `details.errors` lists each problem. Publishing: `CONFIG_TOO_LARGE` (the rendered config would exceed 1 MiB; `details.size_bytes`, `max_bytes`) or `LIMIT_EXCEEDED` with `details.limit: comparison_values_per_config` (over 20,000 comparison values in the config); the write is not applied.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","INVALID_VALUE","INVALID_TARGETING","NOTE_REQUIRED","CONFIG_TOO_LARGE","LIMIT_EXCEEDED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Update a value","tags":["settings"],"x-pc-sdk":{"resource":"settings.values","method":"update","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/settings/{setting_id}/values/{environment_id}/confidential":{"get":{"description":"The cleartext of this value's confidential lists, decrypted. Needs `flags.confidential.read` on the environment and the setting; every call is recorded in the history (`confidential.revealed`). Never cached.","operationId":"SettingsController_revealValue","parameters":[{"name":"setting_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the setting.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The confidential lists, in rule and condition order.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfidentialRevealResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`SETTING_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","SETTING_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"422":{"description":"`CONFIDENTIAL_LIST_NOT_EDITABLE`: every confidential list was sent pre-hashed, so there is no cleartext.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","CONFIDENTIAL_LIST_NOT_EDITABLE"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Reveal confidential values","tags":["settings"],"x-pc-sdk":{"resource":"settings.values","method":"revealConfidential","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/sdk-keys":{"get":{"description":"The SDK keys of this config in this environment, masked (prefix and last four characters): the primary key, and the secondary key while a rotation's grace period runs. The first call for a new environment mints its primary key.","operationId":"SdkKeysController_list","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The masked keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SdkKeyListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`: no such config in this workspace, or the environment is not one of its project.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List SDK keys","tags":["sdk-keys"],"x-pc-sdk":{"resource":"configs.environments.sdkKeys","method":"list","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/sdk-keys/reveal":{"post":{"description":"The full primary key, and the secondary key while a grace period runs. Needs `flags.sdk_key.reveal`; every call is recorded in the history (`sdk_key.revealed`) and the workspace audit log. Never cached. Whoever holds a key can download the whole config of this environment: keep server keys server-side.","operationId":"SdkKeysController_reveal","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The full keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevealedSdkKeyListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`: no such config in this workspace, or the environment is not one of its project.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Reveal SDK keys","tags":["sdk-keys"],"x-pc-sdk":{"resource":"configs.environments.sdkKeys","method":"reveal","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/sdk-keys/rotate":{"post":{"description":"Mints a new primary key. The current primary becomes the secondary key and keeps working for `grace_hours` (default 24, at most 168; `0` revokes it at once); a previous secondary key is revoked. SDK servers pick up the change within about 5 seconds. The response is masked: reveal the new key separately.","operationId":"SdkKeysController_rotate","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Idempotency key (1-256 characters, `[A-Za-z0-9_-:]`). A retry with the same key and body returns the first response for 24 h.","required":false,"schema":{"type":"string"}},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateSdkKeyDto"}}}},"responses":{"200":{"description":"The masked keys after the rotation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SdkKeyListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: `grace_hours` is not an integer from 0 to 168, or `note` is too long.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`: no such config in this workspace, or the environment is not one of its project.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"409":{"description":"Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Rotate the SDK key","tags":["sdk-keys"],"x-pc-sdk":{"resource":"configs.environments.sdkKeys","method":"rotate","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/sdk-keys/secondary":{"delete":{"description":"Revokes the secondary key now instead of at its `expires_at`. SDK servers still using it get 404 within about 5 seconds. Recorded in the history (`sdk_key.grace_ended`) and the workspace audit log.","operationId":"SdkKeysController_endGracePeriod","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The masked keys left (the primary key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SdkKeyListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`: no such config in this workspace, or the environment is not one of its project. `SDK_KEY_NOT_FOUND`: there is no secondary key.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND","SDK_KEY_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"End the grace period","tags":["sdk-keys"],"x-pc-sdk":{"resource":"configs.environments.sdkKeys","method":"endGracePeriod","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/evaluate":{"post":{"description":"Evaluates a sample user against the published config of this environment (the current revision, or `revision`) with the same engine the SDKs run, and returns the evaluation details per key: value, reason, the rule and percentage option that decided, and soft-miss warnings. Each setting's own value is the default. Nothing is stored and the user is never logged. Limited to 30 calls a minute per credential; the evaluation has a 250 ms budget (422 `EVALUATION_BUDGET_EXCEEDED`, ask for fewer keys).","operationId":"EvaluateController_evaluate","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of an environment of the same project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateRequestDto"}}}},"responses":{"200":{"description":"The evaluation details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEvaluationResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: `user` is not an object or null, it has more than 200 attributes, more than 200 `keys`, or a bad `revision`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND`: no such config in this workspace, or the environment is not one of its project. `REVISION_NOT_FOUND`: the requested revision was pruned or never published.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND","REVISION_NOT_FOUND"]},"422":{"description":"`EVALUATION_BUDGET_EXCEEDED`: the evaluation ran over 250 ms; ask for fewer keys. `INVALID_TARGETING`: the stored revision is not a config the engine accepts.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","EVALUATION_BUDGET_EXCEEDED","INVALID_TARGETING"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Test an evaluation","tags":["evaluate"],"x-pc-sdk":{"resource":"configs.environments","method":"evaluate","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/projects/{project_id}/changes":{"get":{"description":"The history of a project, newest first: every write with who made it (user, API key, or a client acting for a user), its note, the config revisions it published and a human summary (\"Production: value false → true\"). Filter by config, environment, setting, segment, actor or time. Confidential lists show as counts, never values.","operationId":"ChangesController_list","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor for pagination: the `next_cursor` of the previous page.","schema":{"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ","type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":50,"type":"integer"},"example":50},{"name":"config_id","required":false,"in":"query","description":"Only changes of this config (its settings, values and keys).","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":false,"in":"query","description":"Only changes in this environment (value writes, SDK keys).","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"setting_id","required":false,"in":"query","description":"Only changes of this setting: its metadata and its values in every environment.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"segment_id","required":false,"in":"query","description":"Only changes of this segment.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"actor_id","required":false,"in":"query","description":"Only changes made by this actor (`actor.id`: a platform user id or an API key id).","schema":{"maxLength":256,"type":"string"}},{"name":"since","required":false,"in":"query","description":"Only changes at or after this time (ISO 8601).","schema":{"format":"date-time","example":"2026-11-01T00:00:00Z","type":"string"},"example":"2026-11-01T00:00:00Z"},{"name":"until","required":false,"in":"query","description":"Only changes before this time (ISO 8601).","schema":{"format":"date-time","example":"2026-11-09T00:00:00Z","type":"string"},"example":"2026-11-09T00:00:00Z"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"A page of changes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeListResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a bad filter, cursor or `limit`, or `since` is not before `until`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List changes","tags":["history"],"x-pc-sdk":{"resource":"projects.changes","method":"list","bind":["workspace_id"],"paginated":true}}},"/v1/workspaces/{workspace_id}/projects/{project_id}/changes/export":{"get":{"description":"The filtered history as a file, newest first, at most 50,000 rows, streamed. `csv`: one row per change with the summary (no bodies). `json`: JSON Lines (`application/x-ndjson`), one change object per line with `before` and `after` (confidential lists as counts). Cells a spreadsheet would run as a formula start with `'`.","operationId":"ChangesController_export","parameters":[{"name":"project_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the project.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"config_id","required":false,"in":"query","description":"Only changes of this config (its settings, values and keys).","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":false,"in":"query","description":"Only changes in this environment (value writes, SDK keys).","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"setting_id","required":false,"in":"query","description":"Only changes of this setting: its metadata and its values in every environment.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"segment_id","required":false,"in":"query","description":"Only changes of this segment.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"actor_id","required":false,"in":"query","description":"Only changes made by this actor (`actor.id`: a platform user id or an API key id).","schema":{"maxLength":256,"type":"string"}},{"name":"since","required":false,"in":"query","description":"Only changes at or after this time (ISO 8601).","schema":{"format":"date-time","example":"2026-11-01T00:00:00Z","type":"string"},"example":"2026-11-01T00:00:00Z"},{"name":"until","required":false,"in":"query","description":"Only changes before this time (ISO 8601).","schema":{"format":"date-time","example":"2026-11-09T00:00:00Z","type":"string"},"example":"2026-11-09T00:00:00Z"},{"name":"format","required":false,"in":"query","description":"`csv` (one row per change, with the summary; no `before` / `after`) or `json` (JSON Lines: one change object per line, with `before` and `after`).","schema":{"$ref":"#/components/schemas/FlagsHistoryExportFormat"},"example":"csv"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The export file (`Content-Disposition: attachment`).","content":{"text/csv":{"schema":{"type":"string"}},"application/x-ndjson":{"schema":{"type":"string","description":"One JSON change object per line."}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a bad filter or `format`, or `since` is not before `until`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`PROJECT_NOT_FOUND`: no such project in this workspace.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","PROJECT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Export changes","tags":["history"],"x-pc-sdk":{"resource":"projects.changes","method":"export","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/changes/{change_id}":{"get":{"description":"One change with `before`, `after`, a JSON Patch `diff` (RFC 6902) and the summary. When `before` and `after` together exceed 64 KB, `diff_too_large` is true and the bodies are left out: compare the revisions in `revisions` (`url`, `previous_url`) instead.","operationId":"ChangesController_get","parameters":[{"name":"change_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the change.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeDetailResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CHANGE_NOT_FOUND`: no such change in this workspace (or it was pruned).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CHANGE_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get a change","tags":["history"],"x-pc-sdk":{"resource":"changes","method":"retrieve","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/changes/{change_id}/revert":{"post":{"description":"Writes the change's `before` back as a new change (`reverts_change_id` points to this one), through the same checks as an edit: validation, the protected-environment and note rules, and publishing. Supported for `setting_value.updated`, `segment.updated` and `setting.updated`. Send the entity's current `version` (the value or segment); a setting is restored only while it is still as this change left it. Needs `flags.value.update` plus what the original edit needed (`flags.value.update` on the environment and setting, or `flags.update`; `flags.protected.update` in protected environments).","operationId":"ChangesController_revert","parameters":[{"name":"change_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the change.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Idempotency key (1-256 characters, `[A-Za-z0-9_-:]`). A retry with the same key and body returns the first response for 24 h.","required":false,"schema":{"type":"string"}},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevertChangeDto"}}}},"responses":{"201":{"description":"The new change (the restore).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeDetailResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: `version` is missing (value and segment restores) or invalid.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`). A restore needs the actions of the original edit too.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CHANGE_NOT_FOUND`; `SETTING_NOT_FOUND`, `SEGMENT_NOT_FOUND` or `ENVIRONMENT_NOT_FOUND` when the entity was deleted since.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CHANGE_NOT_FOUND","SETTING_NOT_FOUND","SEGMENT_NOT_FOUND","ENVIRONMENT_NOT_FOUND"]},"409":{"description":"`VERSION_CONFLICT`: the entity changed since you read it (`details.current_version`), or the setting no longer matches this change. `KEY_ALREADY_EXISTS`: the restored key is taken. Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","VERSION_CONFLICT","KEY_ALREADY_EXISTS","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"`REVERT_NOT_SUPPORTED`: this kind of change cannot be restored. `NOTHING_TO_RESTORE`: it already matches the version before this change. The restored or copied targeting is refused by the normal write checks: `INVALID_VALUE`, `INVALID_TARGETING`, `SEGMENT_NOT_FOUND` (a segment it used was deleted), `PREREQUISITE_NOT_FOUND`, `PREREQUISITE_TYPE_MISMATCH`, `CIRCULAR_PREREQUISITE`, `CONFIDENTIAL_LIST_NOT_EDITABLE`, `LIMIT_EXCEEDED`, `NOTE_REQUIRED` (the environment requires a `note`), `CONFIG_TOO_LARGE`, or `OWNER_NOT_A_MEMBER` (a restored owner left the workspace).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","REVERT_NOT_SUPPORTED","NOTHING_TO_RESTORE","INVALID_VALUE","INVALID_TARGETING","SEGMENT_NOT_FOUND","PREREQUISITE_NOT_FOUND","PREREQUISITE_TYPE_MISMATCH","CIRCULAR_PREREQUISITE","CONFIDENTIAL_LIST_NOT_EDITABLE","LIMIT_EXCEEDED","NOTE_REQUIRED","CONFIG_TOO_LARGE","OWNER_NOT_A_MEMBER"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Restore a version","tags":["history"],"x-pc-sdk":{"resource":"changes","method":"revert","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/configs/{config_id}/environments/{environment_id}/copy":{"post":{"description":"Copies value and targeting (rules, splits, split attribute) of `setting_ids`, or of every setting that differs (`all_differing: true`), from `source_environment_id` into this environment. All or nothing: send the target `version` of every setting that will be copied in `versions`; if any moved, nothing is written and 409 lists them. Publishes one config revision, with one history entry per setting. Needs `flags.value.update` on this environment and each setting, plus `flags.protected.update` when it is protected.","operationId":"CopyEnvironmentController_copy","parameters":[{"name":"config_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the config.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the target environment (same project as the config).","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Idempotency key (1-256 characters, `[A-Za-z0-9_-:]`). A retry with the same key and body returns the first response for 24 h.","required":false,"schema":{"type":"string"}},{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopyEnvironmentDto"}}}},"responses":{"200":{"description":"What was copied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopyEnvironmentResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: neither or both of `setting_ids` / `all_differing`, the source is the target, or a bad `versions` entry.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`). Copies need `flags.value.update` on the environment and every setting, and `flags.protected.update` into a protected environment.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`CONFIG_NOT_FOUND`, `ENVIRONMENT_NOT_FOUND` (target or source is not of this project) or `SETTING_NOT_FOUND`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","CONFIG_NOT_FOUND","ENVIRONMENT_NOT_FOUND","SETTING_NOT_FOUND"]},"409":{"description":"`VERSION_CONFLICT`: a setting changed in the target since you read it, or has no entry in `versions` (`details.conflicts[]`: `setting_id`, `key`, `current_version`, `sent_version`); nothing was copied. Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","VERSION_CONFLICT","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"The restored or copied targeting is refused by the normal write checks: `INVALID_VALUE`, `INVALID_TARGETING`, `SEGMENT_NOT_FOUND` (a segment it used was deleted), `PREREQUISITE_NOT_FOUND`, `PREREQUISITE_TYPE_MISMATCH`, `CIRCULAR_PREREQUISITE`, `CONFIDENTIAL_LIST_NOT_EDITABLE`, `LIMIT_EXCEEDED`, `NOTE_REQUIRED` (the environment requires a `note`), `CONFIG_TOO_LARGE`, or `OWNER_NOT_A_MEMBER` (a restored owner left the workspace).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","INVALID_VALUE","INVALID_TARGETING","SEGMENT_NOT_FOUND","PREREQUISITE_NOT_FOUND","PREREQUISITE_TYPE_MISMATCH","CIRCULAR_PREREQUISITE","CONFIDENTIAL_LIST_NOT_EDITABLE","LIMIT_EXCEEDED","NOTE_REQUIRED","CONFIG_TOO_LARGE","OWNER_NOT_A_MEMBER"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Copy targeting between environments","tags":["settings"],"x-pc-sdk":{"resource":"configs.environments","method":"copy","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/webhooks/event-types":{"get":{"description":"Each type with a plain description, its group and an example `data` object (what \"Send test\" delivers).","operationId":"WebhooksController_flags_workspace_listEventTypes","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhookEventTypesResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List the events an endpoint can subscribe to.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.eventTypes","method":"list","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/webhooks/endpoints":{"get":{"description":"At most 10, so this is always one page. Signing secrets are never returned here, only their last 4 characters.","operationId":"WebhooksController_flags_workspace_listEndpoints","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhookEndpointsResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"The scope id in the path is malformed.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List webhook endpoints, oldest first.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.endpoints","method":"list","bind":["workspace_id"],"paginated":true}},"post":{"description":"Deliveries are signed with the Standard Webhooks headers `webhook-id`, `webhook-timestamp` and `webhook-signature` (`v1,<base64 HMAC-SHA256 of \"<id>.<timestamp>.<body>\">`); the returned `whsec_…` secret works unchanged with any Standard Webhooks library. Failed deliveries are retried after 1 min, 5 min, 30 min, 2 h, 6 h and 24 h.","operationId":"WebhooksController_flags_workspace_createEndpoint","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Opaque client-generated string (1-256 chars, `[A-Za-z0-9_-:]`) that makes a retry of this request safe for 24 hours. The same key with a different body returns 409 `IDEMPOTENCY_KEY_REUSE`.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecretDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"Validation failure: URL not https with a public host, or an unknown event type (`WEBHOOK_EVENT_TYPE_UNKNOWN`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR","WEBHOOK_EVENT_TYPE_UNKNOWN"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"409":{"description":"Already 10 endpoints (`WEBHOOK_ENDPOINT_LIMIT`), or Idempotency-Key reused with a different body (`IDEMPOTENCY_KEY_REUSE`). Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","WEBHOOK_ENDPOINT_LIMIT","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"The URL points at a private, loopback or internal address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Add a webhook endpoint. Returns its signing secret once.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.endpoints","method":"create","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/webhooks/endpoints/{endpoint_id}":{"get":{"description":"The endpoint's URL, subscription, on/off state, failure streak and the last 4 characters of its signing secret. The full secret is only returned when the endpoint is created or its secret is rotated.","operationId":"WebhooksController_flags_workspace_getEndpoint","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"endpoint_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the endpoint.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`endpoint_id` is not a UUID.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"No such endpoint here (`WEBHOOK_ENDPOINT_NOT_FOUND`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","WEBHOOK_ENDPOINT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get one webhook endpoint (without its secret).","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.endpoints","method":"retrieve","bind":["workspace_id"],"paginated":false}},"patch":{"description":"Only the fields sent change. `enabled: true` (or a new URL) also clears an automatic disable. Switching off cancels queued retries. The secret is unchanged; rotate it with `POST …/rotate-secret`.","operationId":"WebhooksController_flags_workspace_updateEndpoint","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"endpoint_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the endpoint.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Opaque client-generated string (1-256 chars, `[A-Za-z0-9_-:]`) that makes a retry of this request safe for 24 hours. The same key with a different body returns 409 `IDEMPOTENCY_KEY_REUSE`.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookEndpointDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"Validation failure, or `endpoint_id` is not a UUID.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"No such endpoint here (`WEBHOOK_ENDPOINT_NOT_FOUND`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","WEBHOOK_ENDPOINT_NOT_FOUND"]},"409":{"description":"Idempotency-Key reused with a different body (`IDEMPOTENCY_KEY_REUSE`). Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"422":{"description":"The new URL points at a private, loopback or internal address.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Change a webhook endpoint: URL, description, events, on/off.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.endpoints","method":"update","bind":["workspace_id"],"paginated":false}},"delete":{"description":"Queued retries are dropped. Its past attempts stay in the event log until the events expire.","operationId":"WebhooksController_flags_workspace_deleteEndpoint","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"endpoint_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the endpoint.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"204":{"description":"Deleted.","headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`endpoint_id` is not a UUID.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"No such endpoint here (`WEBHOOK_ENDPOINT_NOT_FOUND`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","WEBHOOK_ENDPOINT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Delete a webhook endpoint.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.endpoints","method":"delete","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/webhooks/endpoints/{endpoint_id}/rotate-secret":{"post":{"description":"For `grace_hours` (default 24) the previous secret keeps signing too: `webhook-signature` then lists one `v1,` signature per secret, so receivers can switch over without dropping a delivery.","operationId":"WebhooksController_flags_workspace_rotateSecret","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"endpoint_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the endpoint.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Opaque client-generated string (1-256 chars, `[A-Za-z0-9_-:]`) that makes a retry of this request safe for 24 hours. The same key with a different body returns 409 `IDEMPOTENCY_KEY_REUSE`.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateWebhookSecretDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecretDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`grace_hours` out of range, or `endpoint_id` is not a UUID.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"No such endpoint here (`WEBHOOK_ENDPOINT_NOT_FOUND`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","WEBHOOK_ENDPOINT_NOT_FOUND"]},"409":{"description":"Idempotency-Key reused with a different body (`IDEMPOTENCY_KEY_REUSE`). Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Rotate the signing secret. The new one is returned once.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.endpoints","method":"rotateSecret","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/webhooks/endpoints/{endpoint_id}/test":{"post":{"description":"Delivers the catalogue example of `event_type`, signed like any delivery, with `\"test\": true` in the body. Works while the endpoint is switched off or not subscribed to that type, is logged in the event log, and is never retried or counted toward an automatic disable. Waits up to 15 s for your receiver.","operationId":"WebhooksController_flags_workspace_sendTest","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"endpoint_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the endpoint.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Opaque client-generated string (1-256 chars, `[A-Za-z0-9_-:]`) that makes a retry of this request safe for 24 hours. The same key with a different body returns 409 `IDEMPOTENCY_KEY_REUSE`.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendWebhookTestDto"}}}},"responses":{"200":{"description":"The attempt, successful or not.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryAttemptDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"Unknown `event_type`, or `endpoint_id` is not a UUID.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"No such endpoint here (`WEBHOOK_ENDPOINT_NOT_FOUND`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","WEBHOOK_ENDPOINT_NOT_FOUND"]},"409":{"description":"Idempotency-Key reused with a different body (`IDEMPOTENCY_KEY_REUSE`). Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Send a test event to this endpoint now and return the result.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.endpoints","method":"test","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/webhooks/events":{"get":{"description":"Every event logged while at least one endpoint existed, with the latest state per endpoint and when the next retry is due.","operationId":"WebhooksController_flags_workspace_listEvents","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"type","required":false,"in":"query","description":"Only these types. Repeat the parameter or comma-separate.","schema":{"type":"array","items":{"type":"string","enum":["config.published","sdk_key.rotated"]}},"example":["config.published"]},{"name":"endpoint_id","required":false,"in":"query","description":"Only events sent (or queued) to this endpoint.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"status","required":false,"in":"query","description":"Only events in this delivery status.","schema":{"$ref":"#/components/schemas/WebhookEventStatus"},"example":"pending"},{"name":"created_after","required":false,"in":"query","description":"Only events created at or after this instant.","schema":{"format":"date-time","type":"string"},"example":"2026-11-01T00:00:00Z"},{"name":"created_before","required":false,"in":"query","description":"Only events created before this instant.","schema":{"format":"date-time","type":"string"},"example":"2026-12-01T00:00:00Z"},{"name":"limit","required":false,"in":"query","description":"Page size.","schema":{"minimum":1,"maximum":100,"default":20,"type":"integer"},"example":20},{"name":"cursor","required":false,"in":"query","description":"The previous page's `pagination.next_cursor`.","schema":{"type":"string"},"example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},{"name":"project_id","required":false,"in":"query","description":"Only events of this project.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"config_id","required":false,"in":"query","description":"Only events of this config.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"environment_id","required":false,"in":"query","description":"Only events of this environment.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhookEventsResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"Invalid filter value or cursor.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"List webhook events, newest first (kept for 30 days).","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.events","method":"list","bind":["workspace_id"],"paginated":true}}},"/v1/workspaces/{workspace_id}/webhooks/events/{event_id}":{"get":{"description":"The event as it was sent (`type`, `data`) and every delivery attempt to every endpoint, with its trigger, HTTP status, error and the start of the response body. Use it to debug a receiver, then `replay` to send it again.","operationId":"WebhooksController_flags_workspace_getEvent","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"event_id","required":true,"in":"path","description":"The event id, `evt_<uuid>`.","schema":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventDetailDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`event_id` is not `evt_<uuid>`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"No such event here (`WEBHOOK_EVENT_NOT_FOUND`); events are kept for 30 days.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","WEBHOOK_EVENT_NOT_FOUND"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get one webhook event with every delivery attempt.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.events","method":"retrieve","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/webhooks/events/{event_id}/replay":{"post":{"description":"Same body and `webhook-id`, freshly signed, to every switched-on endpoint that receives this event type now, or only to `endpoint_id`. Waits for the receivers (up to 15 s each) and returns the attempts. A success cancels a retry still queued for that endpoint.","operationId":"WebhooksController_flags_workspace_replay","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"event_id","required":true,"in":"path","description":"The event id, `evt_<uuid>`.","schema":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$"}},{"name":"endpoint_id","required":false,"in":"query","description":"Send to this endpoint only.","schema":{"format":"uuid","type":"string"},"example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"Idempotency-Key","in":"header","description":"Opaque client-generated string (1-256 chars, `[A-Za-z0-9_-:]`) that makes a retry of this request safe for 24 hours. The same key with a different body returns 409 `IDEMPOTENCY_KEY_REUSE`.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplayWebhookEventResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"Idempotent-Replay":{"description":"`true` when this response is a replay of an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`event_id` is not `evt_<uuid>`, or `endpoint_id` is not a UUID.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"401":{"description":"Missing or invalid bearer token.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNAUTHORIZED"]},"403":{"description":"Caller lacks `flags.webhook.read` (reads) or `flags.webhook.manage` (changes, Send test, replay), or Flags is not enabled for the workspace (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"No such event here (`WEBHOOK_EVENT_NOT_FOUND`); events are kept for 30 days. Or No such endpoint here (`WEBHOOK_ENDPOINT_NOT_FOUND`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","WEBHOOK_EVENT_NOT_FOUND","WEBHOOK_ENDPOINT_NOT_FOUND"]},"409":{"description":"`endpoint_id` is switched off or does not receive this event type (`WEBHOOK_ENDPOINT_NOT_SUBSCRIBED`), or Idempotency-Key reused with a different body (`IDEMPOTENCY_KEY_REUSE`). Idempotency: `IDEMPOTENCY_KEY_REUSE` when this `Idempotency-Key` was already used with a different body or route; `IDEMPOTENCY_IN_PROGRESS` while another request with the same key is still running (retry after `Retry-After` seconds, with the same key).","headers":{"Retry-After":{"description":"Seconds to wait before retrying with the same key (sent with `IDEMPOTENCY_IN_PROGRESS`).","schema":{"type":"integer"}},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","WEBHOOK_ENDPOINT_NOT_SUBSCRIBED","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_IN_PROGRESS"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Send a logged event again, to its endpoints or to one endpoint.","tags":["webhooks"],"x-pc-sdk":{"resource":"webhooks.events","method":"replay","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/stats":{"get":{"description":"Counts for the workspace: projects, configs, flags and settings, segments, changes in the last 7 days and when the latest change was made, plus each project’s history usage against the retention caps (50,000 rows or 200 MiB per project; `warning` from 80%). Counts only: no keys, values or rules.","operationId":"StatsController_get","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"format":"uuid","type":"string"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"responses":{"200":{"description":"The stats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagsStatsResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]}},"security":[{"bearer":[]}],"summary":"Get Flags stats","tags":["stats"],"x-pc-sdk":{"resource":"stats","method":"retrieve","bind":["workspace_id"],"paginated":false}}},"/v1/workspaces/{workspace_id}/imports":{"post":{"description":"Reads a ConfigCat product through ConfigCat's Public Management API with credentials you send for this one request (never stored, logged or cached), and maps it to a new Flags project: environments, configs, feature flags and settings (seed = the ConfigCat key, so every user stays in the same percentage bucket), segments, targeting rules, percentage options and prerequisite flags; sensitive comparators become confidential comparators re-hashed under the project salt. Send `dry_run: true` first: it reads and reports (`counts`, `mapped`, `unsupported`, `warnings`) and writes nothing. A real run (`dry_run: false`) creates the project and answers 201; while the report lists `unsupported` items it answers 422 `IMPORT_UNSUPPORTED` unless `skip_unsupported: true`. One synchronous call with a 120 s budget for the ConfigCat reads (paced to ConfigCat's rate limits). Needs `flags.project.manage` and `flags.create`. No Idempotency-Key: the body carries credentials, and a retry of a finished import answers 409 `KEY_ALREADY_EXISTS` (the project name is taken).","operationId":"ImportsController_create","parameters":[{"name":"workspace_id","required":true,"in":"path","schema":{"type":"string","format":"uuid"},"description":"Id of the workspace.","example":"3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateImportDto"}}}},"responses":{"200":{"description":"Dry run: the report; nothing was written.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"201":{"description":"Real run: the new project and the report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResponseDto"}}},"headers":{"X-RateLimit-Limit-short":{"$ref":"#/components/headers/X-RateLimit-Limit-short"},"X-RateLimit-Remaining-short":{"$ref":"#/components/headers/X-RateLimit-Remaining-short"},"X-RateLimit-Reset-short":{"$ref":"#/components/headers/X-RateLimit-Reset-short"},"X-RateLimit-Limit-long":{"$ref":"#/components/headers/X-RateLimit-Limit-long"},"X-RateLimit-Remaining-long":{"$ref":"#/components/headers/X-RateLimit-Remaining-long"},"X-RateLimit-Reset-long":{"$ref":"#/components/headers/X-RateLimit-Reset-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}}},"400":{"description":"`VALIDATION_ERROR`: a field is missing or invalid (`source` must be `configcat`, `configcat_product_id` a uuid).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_REQUEST","VALIDATION_ERROR"]},"403":{"description":"The caller lacks the action this route needs (`message` names it), or the workspace has not enabled Flags (`SERVICE_NOT_ENABLED`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["FORBIDDEN","SERVICE_NOT_ENABLED"]},"404":{"description":"`IMPORT_SOURCE_NOT_FOUND`: the ConfigCat product does not exist, or the credentials cannot see it.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["NOT_FOUND","IMPORT_SOURCE_NOT_FOUND"]},"409":{"description":"`KEY_ALREADY_EXISTS`: a project with the target name already exists (pass `target_project_name`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["CONFLICT","KEY_ALREADY_EXISTS"]},"422":{"description":"`IMPORT_CREDENTIALS_INVALID`: ConfigCat rejected the credentials. `IMPORT_UNSUPPORTED`: a real run while the report lists unsupported items (`details.items`); send `skip_unsupported: true` to import without them. `IMPORT_EXCEEDS_LIMITS`: the product is larger than the Flags limits, or reading it ran over the 120 s budget (`details`: `limit`, `max`, `current`). Nothing was imported.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["UNPROCESSABLE_ENTITY","IMPORT_CREDENTIALS_INVALID","IMPORT_UNSUPPORTED","IMPORT_EXCEEDS_LIMITS"]},"429":{"description":"More than 20 requests per second or 600 per minute from this client IP (`RATE_LIMITED`); wait `Retry-After` seconds.","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"Retry-After-short":{"$ref":"#/components/headers/Retry-After-short"},"Retry-After-long":{"$ref":"#/components/headers/Retry-After-long"},"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["RATE_LIMITED"]},"502":{"description":"`IMPORT_SOURCE_UNAVAILABLE`: ConfigCat answered 5xx, timed out or could not be reached.","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"x-pc-error-codes":["BAD_GATEWAY","IMPORT_SOURCE_UNAVAILABLE"]}},"security":[{"bearer":[]}],"summary":"Import from ConfigCat","tags":["imports"],"x-pc-sdk":{"resource":"imports","method":"create","bind":["workspace_id"],"paginated":false}}}},"info":{"title":"Flags API","description":"Feature flags and remote settings for the ProductCraft platform. Manage projects, environments, configs, flags, targeting rules and segments here; SDKs download a compact config per environment and evaluate flags locally, so user attributes never leave your app.\n\n## Rate limits\n\nEvery `/v1` route is limited per client IP to 20 requests per second and 600 per minute. Each response carries `X-RateLimit-Limit-short`, `X-RateLimit-Remaining-short`, `X-RateLimit-Reset-short` (the one-second window) and the same three with `-long` (the one-minute window). Over either limit the response is `429` with code `RATE_LIMITED` and a `Retry-After` header in seconds.\n\nFlags counts these limits per credential (API key or session), not per IP, and allows at most 120 writes (POST, PUT, PATCH, DELETE) a minute within them.","version":"0.1.0","contact":{}},"tags":[{"name":"Delivery","description":"The public config download SDKs poll: `GET /v1/configs/{sdk_key}/config.json` with ETag/304, compressed bodies and CORS for browsers. Authenticated by the SDK key alone; not part of the management client."},{"name":"configs","description":"A config is the unit an SDK downloads: one JSON document per environment, with its own SDK key. Most projects need only `main`."},{"name":"environments","description":"Environments of a project (for example Development, Staging, Production). Each has its own values and SDK keys; protected environments need `flags.protected.update` for value changes."},{"name":"evaluate","description":"Test evaluations: evaluate a sample user against a published config with the same engine the SDKs run, and see the value, the reason and the rule or percentage option that decided. Nothing is stored and the user is never logged."},{"name":"history","description":"The change history of a project: every write with who made it, its note, the config revisions it published, a diff and a human summary. Restore a version, export the history as CSV or JSON. Confidential lists show as counts, never values."},{"name":"imports","description":"Move in from ConfigCat in one step: a dry run reports what maps, what does not and what changes form; the real run creates a project with the same environments, configs, flags, segments and targeting, and keeps every user in the same percentage bucket."},{"name":"limits","description":"The preview limits of Flags and how much of them the workspace uses."},{"name":"projects","description":"A project groups the environments, configs, flags and segments of one product. New projects start with Development, a protected Production and one config, `main`."},{"name":"revisions","description":"Published config revisions per environment: every write that changes what SDKs download publishes a new revision of the config JSON. List them and read any kept revision byte for byte as SDKs get it."},{"name":"sdk-keys","description":"SDK keys, one primary per config and environment: list them masked, reveal them (audited), rotate with a grace period during which the old key keeps working, or end the grace period early."},{"name":"segments","description":"Reusable sets of ANDed user conditions per project, targeted by rules of any config with `in` / `not_in`. Confidential (hashed) conditions keep only salted hashes in the SDK config and the cleartext encrypted for editing and reveal."},{"name":"settings","description":"Feature flags (`boolean`) and typed settings (`string`, `integer`, `number`, `json`) of a config, and their value and targeting per environment: rules on user attributes and prerequisite flags, percentage splits, and optimistic concurrency through `version`."},{"name":"stats","description":"Workspace counts for dashboards: projects, configs, flags and settings, segments, recent changes, and history usage per project against the retention caps."},{"name":"webhooks","description":"Signed webhooks (Standard Webhooks) for `config.published` (a new config revision in an environment) and `sdk_key.rotated`, with endpoints filtered by project, config or environment, an event log, retries, Send test and replay."}],"servers":[{"url":"https://api.flags.productcraft.co","description":"Flags API"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"ConfigRevisionResponseDto":{"type":"object","properties":{"revision":{"type":"integer","description":"The revision number, monotonic per (config, environment) within a generation.","example":2},"generation":{"type":"integer","description":"The generation the revision was published under; it changes only after a database restore, and a new generation restarts the SDK revision guard.","example":1},"etag":{"type":"string","description":"The ETag SDKs see for this revision (22 characters, b64url).","example":"q8w4Yb0cJ0dY2t1vUo3n7A"},"size_bytes":{"type":"integer","description":"Size of the config JSON in bytes, uncompressed.","example":412},"published_at":{"type":"string","format":"date-time","description":"When the revision was published."},"change_id":{"type":"string","format":"uuid","nullable":true,"description":"The change (history entry) that published the revision. History retention can remove the change itself later."},"current":{"type":"boolean","description":"Whether this is the revision SDKs are served now.","example":true}},"required":["revision","generation","etag","size_bytes","published_at","change_id","current"],"x-pc-sdk-model":"ConfigRevision"},"FlagsPaginationDto":{"type":"object","properties":{"next_cursor":{"type":"string","nullable":true,"description":"Pass as `cursor` to get the next page; `null` on the last page.","example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0xMS0wMVQwMDowMDowMFoifQ"},"has_more":{"type":"boolean","description":"Whether another page exists.","example":false}},"required":["next_cursor","has_more"],"x-pc-sdk-model":"FlagsPagination"},"ConfigRevisionListResponseDto":{"type":"object","properties":{"data":{"description":"Published revisions, newest first (the last 100, or 20 MiB of compressed snapshots, are kept).","type":"array","items":{"$ref":"#/components/schemas/ConfigRevisionResponseDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/FlagsPaginationDto"}]}},"required":["data","pagination"],"x-pc-sdk-model":"ConfigRevisionList"},"EnvironmentResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The environment's id."},"workspace_id":{"type":"string","format":"uuid","description":"The workspace that owns the environment."},"project_id":{"type":"string","format":"uuid","description":"The project the environment belongs to."},"key":{"type":"string","description":"Stable key, unique in the project. Cannot change.","example":"production"},"name":{"type":"string","description":"Display name.","example":"Production"},"color":{"type":"string","description":"Display color, `#rrggbb`.","example":"#c92a2a"},"ordinal":{"type":"integer","description":"Sort position in the project (ascending).","example":1},"protected":{"type":"boolean","description":"Protected environments need `flags.protected.update` (owners and admins by default) for any value change, on top of `flags.value.update`.","example":true},"require_note":{"type":"boolean","description":"Value changes in this environment must carry a `note`.","example":false},"created_at":{"type":"string","format":"date-time","description":"When the environment was created."},"updated_at":{"type":"string","format":"date-time","description":"When the environment last changed."}},"required":["id","workspace_id","project_id","key","name","color","ordinal","protected","require_note","created_at","updated_at"],"x-pc-sdk-model":"Environment"},"ConfigResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The config's id."},"workspace_id":{"type":"string","format":"uuid","description":"The workspace that owns the config."},"project_id":{"type":"string","format":"uuid","description":"The project the config belongs to."},"key":{"type":"string","description":"Stable key, unique in the project.","example":"main"},"name":{"type":"string","description":"Display name.","example":"Main"},"description":{"type":"string","description":"Free-text description (may be empty).","example":""},"ordinal":{"type":"integer","description":"Sort position in the project (ascending).","example":0},"created_at":{"type":"string","format":"date-time","description":"When the config was created."},"updated_at":{"type":"string","format":"date-time","description":"When the config last changed."}},"required":["id","workspace_id","project_id","key","name","description","ordinal","created_at","updated_at"],"x-pc-sdk-model":"Config"},"ProjectResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The project's id."},"workspace_id":{"type":"string","format":"uuid","description":"The workspace that owns the project."},"name":{"type":"string","description":"Display name, unique in the workspace (case-insensitive).","example":"Storefront"},"description":{"type":"string","description":"Free-text description (may be empty).","example":""},"ordinal":{"type":"integer","description":"Sort position in the workspace (ascending).","example":0},"environments":{"description":"The project's environments, in `ordinal` order.","type":"array","items":{"$ref":"#/components/schemas/EnvironmentResponseDto"}},"configs":{"description":"The project's configs, in `ordinal` order.","type":"array","items":{"$ref":"#/components/schemas/ConfigResponseDto"}},"created_at":{"type":"string","format":"date-time","description":"When the project was created."},"updated_at":{"type":"string","format":"date-time","description":"When the project last changed."}},"required":["id","workspace_id","name","description","ordinal","environments","configs","created_at","updated_at"],"x-pc-sdk-model":"Project"},"ProjectListResponseDto":{"type":"object","properties":{"data":{"description":"Projects, oldest first.","type":"array","items":{"$ref":"#/components/schemas/ProjectResponseDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/FlagsPaginationDto"}]}},"required":["data","pagination"],"x-pc-sdk-model":"ProjectList"},"FlagsEnvironmentPreset":{"type":"string","enum":["dev_prod","dev_staging_prod"]},"ProjectEnvironmentInputDto":{"type":"object","properties":{"key":{"type":"string","description":"Stable key, unique in the project; must be a lowercase slug: a-z, 0-9 and \"-\", 1-63 characters, not starting with \"-\".","example":"production"},"name":{"type":"string","description":"Display name, 1-100 characters.","example":"Production"},"color":{"type":"string","description":"Display color, `#rrggbb`.","example":"#c92a2a"},"protected":{"type":"boolean","description":"Defaults to true for the key `production`, else false."},"require_note":{"type":"boolean","description":"Require a `note` on value changes. Defaults to false."}},"required":["key","name"]},"ProjectConfigInputDto":{"type":"object","properties":{"key":{"type":"string","description":"Stable key, unique in the project; must be a lowercase slug: a-z, 0-9 and \"-\", 1-63 characters, not starting with \"-\".","example":"main"},"name":{"type":"string","description":"Display name, 1-100 characters.","example":"Main"},"description":{"type":"string","description":"Free-text description, at most 1000 characters."}},"required":["key","name"]},"CreateProjectDto":{"type":"object","properties":{"name":{"type":"string","description":"Display name, 1-100 characters, unique in the workspace.","example":"Storefront"},"description":{"type":"string","description":"Free-text description, at most 1000 characters."},"environment_preset":{"default":"dev_prod","description":"The environments to start with when `environments` is not given: `dev_prod` (Development, Production) or `dev_staging_prod` (Development, Staging, Production). Production is protected.","allOf":[{"$ref":"#/components/schemas/FlagsEnvironmentPreset"}]},"environments":{"description":"Your own environment list instead of a preset (1-5).","type":"array","items":{"$ref":"#/components/schemas/ProjectEnvironmentInputDto"}},"configs":{"description":"Your own config list instead of the default \"Main\" config (1-10).","type":"array","items":{"$ref":"#/components/schemas/ProjectConfigInputDto"}},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"}},"required":["name"]},"UpdateProjectDto":{"type":"object","properties":{"name":{"type":"string","description":"Display name, 1-100 characters, unique in the workspace.","example":"Storefront"},"description":{"type":"string","description":"Free-text description, at most 1000 characters."},"ordinal":{"type":"integer","description":"Sort position in the workspace.","example":0},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"}}},"FlagsLimitDto":{"type":"object","properties":{"limit":{"type":"string","description":"Limit name.","example":"projects"},"scope":{"type":"string","description":"What the limit counts per: `workspace`, `project`, `config`, `setting_value`, `rule`, `condition`, `setting`.","example":"workspace"},"max":{"type":"integer","description":"The maximum.","example":3}},"required":["limit","scope","max"],"x-pc-sdk-model":"FlagsLimit"},"FlagsProjectUsageDto":{"type":"object","properties":{"project_id":{"type":"string","format":"uuid","description":"The project."},"name":{"type":"string","description":"The project's name.","example":"Storefront"},"environments":{"type":"integer","description":"Environments in the project.","example":2},"configs":{"type":"integer","description":"Configs in the project.","example":1},"segments":{"type":"integer","description":"Segments in the project.","example":0}},"required":["project_id","name","environments","configs","segments"],"x-pc-sdk-model":"FlagsProjectUsage"},"FlagsUsageDto":{"type":"object","properties":{"projects":{"type":"integer","description":"Projects in the workspace.","example":1},"per_project":{"description":"Per-project counts.","type":"array","items":{"$ref":"#/components/schemas/FlagsProjectUsageDto"}}},"required":["projects","per_project"],"x-pc-sdk-model":"FlagsUsage"},"FlagsLimitsResponseDto":{"type":"object","properties":{"limits":{"description":"The preview limits. A write past one answers 422 `LIMIT_EXCEEDED`.","type":"array","items":{"$ref":"#/components/schemas/FlagsLimitDto"}},"usage":{"description":"Current usage of the counted limits.","allOf":[{"$ref":"#/components/schemas/FlagsUsageDto"}]}},"required":["limits","usage"],"x-pc-sdk-model":"FlagsLimits"},"EnvironmentListResponseDto":{"type":"object","properties":{"data":{"description":"Every environment of the project (at most 5), in `ordinal` order.","type":"array","items":{"$ref":"#/components/schemas/EnvironmentResponseDto"}}},"required":["data"],"x-pc-sdk-model":"EnvironmentList"},"CreateEnvironmentDto":{"type":"object","properties":{"key":{"type":"string","description":"Stable key, unique in the project; must be a lowercase slug: a-z, 0-9 and \"-\", 1-63 characters, not starting with \"-\". Cannot change later.","example":"staging"},"name":{"type":"string","description":"Display name, 1-100 characters.","example":"Staging"},"color":{"type":"string","description":"Display color, `#rrggbb`. Defaults to gray.","example":"#e67700"},"ordinal":{"type":"integer","description":"Sort position. Defaults to after the last one.","example":1},"protected":{"type":"boolean","description":"Require `flags.protected.update` for value changes. Defaults to true for the key `production`, else false."},"require_note":{"type":"boolean","description":"Require a `note` on value changes. Defaults to false."},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"}},"required":["key","name"]},"UpdateEnvironmentDto":{"type":"object","properties":{"name":{"type":"string","description":"Display name, 1-100 characters.","example":"Staging"},"color":{"type":"string","description":"Display color, `#rrggbb`.","example":"#e67700"},"ordinal":{"type":"integer","description":"Sort position.","example":1},"protected":{"type":"boolean","description":"Protect the environment (or lift the protection)."},"require_note":{"type":"boolean","description":"Require a `note` on value changes."},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"}}},"ConfigListResponseDto":{"type":"object","properties":{"data":{"description":"Configs, in `ordinal` order.","type":"array","items":{"$ref":"#/components/schemas/ConfigResponseDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/FlagsPaginationDto"}]}},"required":["data","pagination"],"x-pc-sdk-model":"ConfigList"},"CreateConfigDto":{"type":"object","properties":{"key":{"type":"string","description":"Stable key, unique in the project; must be a lowercase slug: a-z, 0-9 and \"-\", 1-63 characters, not starting with \"-\".","example":"checkout"},"name":{"type":"string","description":"Display name, 1-100 characters.","example":"Checkout"},"description":{"type":"string","description":"Free-text description, at most 1000 characters.","example":""},"ordinal":{"type":"integer","description":"Sort position. Defaults to after the last one.","example":1},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"}},"required":["key","name"]},"UpdateConfigDto":{"type":"object","properties":{"key":{"type":"string","description":"New key; must be a lowercase slug: a-z, 0-9 and \"-\", 1-63 characters, not starting with \"-\". SDKs address configs by SDK key, not by this key.","example":"checkout"},"name":{"type":"string","description":"Display name, 1-100 characters.","example":"Checkout"},"description":{"type":"string","description":"Free-text description, at most 1000 characters."},"ordinal":{"type":"integer","description":"Sort position.","example":1},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"}}},"HashedValuesViewDto":{"type":"object","properties":{"hashed":{"type":"boolean","description":"Always true: the list is confidential and only its count is shown.","example":true},"count":{"type":"integer","description":"How many values the list holds.","example":3},"list_id":{"type":"string","format":"uuid","description":"Names this list within its setting value or segment. Send it back (as `list_id`, or by echoing this object as `values`) to keep the list in a PUT, or with `values_add` / `values_remove` to edit it."},"editable":{"type":"boolean","description":"Whether the cleartext is kept (encrypted), so the list can be revealed and edited. False for a list sent pre-hashed with `values_hashed`.","example":true}},"required":["hashed","count","list_id","editable"],"x-pc-sdk-model":"HashedValuesView"},"FlagsUserComparator":{"type":"string","enum":["eq","neq","one_of","not_one_of","contains_any","not_contains_any","starts_with_any","not_starts_with_any","ends_with_any","not_ends_with_any","semver_one_of","semver_not_one_of","semver_lt","semver_lte","semver_gt","semver_gte","num_eq","num_neq","num_lt","num_lte","num_gt","num_gte","before","after","array_contains_any","array_not_contains_any","eq_hashed","neq_hashed","one_of_hashed","not_one_of_hashed","starts_with_any_hashed","not_starts_with_any_hashed","ends_with_any_hashed","not_ends_with_any_hashed","array_contains_any_hashed","array_not_contains_any_hashed"]},"UserConditionBodyDto":{"type":"object","properties":{"attribute":{"type":"string","description":"The user attribute to compare: `identifier`, `email`, `country`, or any custom attribute name. Case-sensitive and returned exactly as sent (`app_version` and `appVersion` are different attributes). 1-256 characters.","example":"app_version"},"comparator":{"description":"Text: `eq`, `neq` (one value), `one_of`, `not_one_of`, `contains_any`, `not_contains_any`, `starts_with_any`, `not_starts_with_any`, `ends_with_any`, `not_ends_with_any`. Semver: `semver_one_of`, `semver_not_one_of`, `semver_lt`, `semver_lte`, `semver_gt`, `semver_gte` (SemVer 2.0.0, no leading \"v\"). Number: `num_eq` … `num_gte` (one value). Date: `before`, `after` (one value: unix seconds or ISO 8601, stored as unix seconds). Array: `array_contains_any`, `array_not_contains_any`. Confidential (hashed): `eq_hashed`, `neq_hashed` (one value), `one_of_hashed`, `not_one_of_hashed`, `starts_with_any_hashed`, `not_starts_with_any_hashed`, `ends_with_any_hashed`, `not_ends_with_any_hashed`, `array_contains_any_hashed`, `array_not_contains_any_hashed`: send cleartext `values`; the API stores only salted SHA-256 hashes (which ship to SDKs) and the cleartext encrypted at rest. Hashing is obfuscation, not secrecy: short or guessable values can be brute-forced, and starts/ends-with hashes reveal the length. All case-sensitive.","example":"semver_gte","allOf":[{"$ref":"#/components/schemas/FlagsUserComparator"}]},"values":{"allOf":[{"$ref":"#/components/schemas/UserConditionValues"}],"description":"Required unless a confidential comparator sends `values_hashed` or `list_id` instead. Comparison values: 1-1000 values and at most 64 KB per condition. Strings for text, semver and array comparators; numbers (or numeric strings) for number comparators; unix seconds or ISO 8601 strings for date comparators; cleartext strings for confidential comparators (duplicates dropped). Responses show a confidential list as `{hashed: true, count, list_id, editable}`; sending that object back keeps the list unchanged.","example":["2.0.0"]},"values_hashed":{"description":"Confidential comparators only, instead of `values`: values already hashed by you (64 lower-case hex characters, or `<n>_` + 64 hex for starts/ends-with). Such a list has no cleartext, so it cannot be revealed or edited later (422 `CONFIDENTIAL_LIST_NOT_EDITABLE`).","type":"array","items":{"type":"string"}},"list_id":{"type":"string","format":"uuid","description":"Confidential comparators only, instead of `values`: keep the stored list with this `list_id` (from a response), optionally edited with `values_add` / `values_remove`."},"values_add":{"description":"With `list_id`: cleartext values to add (set semantics).","example":["@beta.test"],"type":"array","items":{"type":"string"}},"values_remove":{"description":"With `list_id`: cleartext values to remove (set semantics; applied before `values_add`).","type":"array","items":{"type":"string"}}},"required":["attribute","comparator"],"x-pc-sdk-model":"UserConditionBody"},"UserConditionDto":{"type":"object","properties":{"user":{"description":"Compare a user attribute.","allOf":[{"$ref":"#/components/schemas/UserConditionBodyDto"}]}},"required":["user"],"x-pc-sdk-model":"UserCondition"},"SegmentResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The segment's id."},"workspace_id":{"type":"string","format":"uuid","description":"The workspace that owns it."},"project_id":{"type":"string","format":"uuid","description":"The project; a segment can be used by any config of it."},"key":{"type":"string","description":"Unique in the project, case-sensitive; SDKs see it in the config JSON.","example":"qa_staff"},"name":{"type":"string","description":"Display name.","example":"QA staff"},"description":{"type":"string","description":"Free-text description (may be empty).","example":""},"seed":{"type":"string","description":"The key at creation. It never changes, and confidential values are hashed with it, so renaming the segment keeps them valid.","example":"qa_staff"},"conditions":{"description":"1-20 conditions, ANDed in order; each is `{user: {attribute, comparator, values}}` (segments hold user conditions only). Confidential comparators take cleartext `values` (stored hashed with the segment's seed and the project salt, and encrypted at rest), `values_hashed`, or `list_id` with `values_add` / `values_remove` to edit a stored list. Confidential lists are shown as `{hashed: true, count, list_id, editable}`.","type":"array","items":{"$ref":"#/components/schemas/UserConditionDto"}},"version":{"type":"integer","description":"Increments on every change; send it with an update to detect concurrent edits.","example":1},"usage_count":{"type":"integer","description":"How many settings use the segment in at least one environment.","example":2},"created_by":{"type":"string","nullable":true,"description":"Who created it (user or API key id)."},"created_at":{"type":"string","format":"date-time","description":"When it was created."},"updated_at":{"type":"string","format":"date-time","description":"When it last changed."}},"required":["id","workspace_id","project_id","key","name","description","seed","conditions","version","usage_count","created_by","created_at","updated_at"],"x-pc-sdk-model":"Segment"},"SegmentListResponseDto":{"type":"object","properties":{"data":{"description":"Segments, oldest first.","type":"array","items":{"$ref":"#/components/schemas/SegmentResponseDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/FlagsPaginationDto"}]}},"required":["data","pagination"],"x-pc-sdk-model":"SegmentList"},"CreateSegmentDto":{"type":"object","properties":{"key":{"type":"string","description":"Unique in the project; must start with a letter and contain only letters, digits, \"_\", \".\" and \"-\", at most 128 characters. Becomes the segment's permanent seed.","example":"qa_staff"},"name":{"type":"string","description":"Display name, 1-200 characters. Defaults to the key.","example":"QA staff"},"description":{"type":"string","description":"Free-text description, at most 1000 characters."},"conditions":{"description":"1-20 conditions, ANDed in order; each is `{user: {attribute, comparator, values}}` (segments hold user conditions only). Confidential comparators take cleartext `values` (stored hashed with the segment's seed and the project salt, and encrypted at rest), `values_hashed`, or `list_id` with `values_add` / `values_remove` to edit a stored list.","example":[{"user":{"attribute":"email","comparator":"ends_with_any_hashed","values":["@acme.test"]}}],"type":"array","items":{"$ref":"#/components/schemas/UserConditionDto"}},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. A segment used in an environment with `require_note` cannot change without one.","maxLength":500,"example":"Add the beta testers domain"}},"required":["key","conditions"]},"SegmentUseDto":{"type":"object","properties":{"setting_id":{"type":"string","format":"uuid","description":"The setting whose rules use the segment."},"setting_key":{"type":"string","description":"The setting's key.","example":"new_checkout"},"config_id":{"type":"string","format":"uuid","description":"The setting's config."},"config_key":{"type":"string","description":"The config's key.","example":"main"},"environment_id":{"type":"string","format":"uuid","description":"The environment where the rules use it."},"environment_key":{"type":"string","description":"The environment's key.","example":"production"}},"required":["setting_id","setting_key","config_id","config_key","environment_id","environment_key"],"x-pc-sdk-model":"SegmentUse"},"SegmentDetailResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The segment's id."},"workspace_id":{"type":"string","format":"uuid","description":"The workspace that owns it."},"project_id":{"type":"string","format":"uuid","description":"The project; a segment can be used by any config of it."},"key":{"type":"string","description":"Unique in the project, case-sensitive; SDKs see it in the config JSON.","example":"qa_staff"},"name":{"type":"string","description":"Display name.","example":"QA staff"},"description":{"type":"string","description":"Free-text description (may be empty).","example":""},"seed":{"type":"string","description":"The key at creation. It never changes, and confidential values are hashed with it, so renaming the segment keeps them valid.","example":"qa_staff"},"conditions":{"description":"1-20 conditions, ANDed in order; each is `{user: {attribute, comparator, values}}` (segments hold user conditions only). Confidential comparators take cleartext `values` (stored hashed with the segment's seed and the project salt, and encrypted at rest), `values_hashed`, or `list_id` with `values_add` / `values_remove` to edit a stored list. Confidential lists are shown as `{hashed: true, count, list_id, editable}`.","type":"array","items":{"$ref":"#/components/schemas/UserConditionDto"}},"version":{"type":"integer","description":"Increments on every change; send it with an update to detect concurrent edits.","example":1},"usage_count":{"type":"integer","description":"How many settings use the segment in at least one environment.","example":2},"created_by":{"type":"string","nullable":true,"description":"Who created it (user or API key id)."},"created_at":{"type":"string","format":"date-time","description":"When it was created."},"updated_at":{"type":"string","format":"date-time","description":"When it last changed."},"used_by":{"description":"Every (setting, environment) whose rules use the segment. A segment listed anywhere cannot be deleted.","type":"array","items":{"$ref":"#/components/schemas/SegmentUseDto"}}},"required":["id","workspace_id","project_id","key","name","description","seed","conditions","version","usage_count","created_by","created_at","updated_at","used_by"],"x-pc-sdk-model":"SegmentDetail"},"UpdateSegmentDto":{"type":"object","properties":{"key":{"type":"string","description":"New key; must start with a letter and contain only letters, digits, \"_\", \".\" and \"-\", at most 128 characters. The seed does not change, so confidential hashes stay valid.","example":"qa_team"},"name":{"type":"string","description":"Display name, 1-200 characters."},"description":{"type":"string","description":"Free-text description, at most 1000 characters."},"conditions":{"description":"Replaces the conditions. 1-20 conditions, ANDed in order; each is `{user: {attribute, comparator, values}}` (segments hold user conditions only). Confidential comparators take cleartext `values` (stored hashed with the segment's seed and the project salt, and encrypted at rest), `values_hashed`, or `list_id` with `values_add` / `values_remove` to edit a stored list. To keep a confidential list, send its `list_id` (or echo the `{hashed: true, list_id, …}` object as `values`).","example":[{"user":{"attribute":"email","comparator":"ends_with_any_hashed","list_id":"3f0c6a3e-0f5e-4b8e-9d1a-2c7b9f1e8a10","values_add":["@beta.test"]}}],"type":"array","items":{"$ref":"#/components/schemas/UserConditionDto"}},"version":{"type":"integer","minimum":1,"description":"The `version` you read; when sent, a mismatch answers 409 `VERSION_CONFLICT`.","example":1},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. A segment used in an environment with `require_note` cannot change without one.","maxLength":500,"example":"Add the beta testers domain"}}},"ConfidentialListDto":{"type":"object","properties":{"rule_index":{"type":"integer","nullable":true,"description":"The rule the list is in (0-based); null for a segment condition.","example":0},"condition_index":{"type":"integer","description":"The condition within the rule or segment (0-based).","example":0},"attribute":{"type":"string","description":"The user attribute the condition compares.","example":"email"},"comparator":{"type":"string","description":"The confidential comparator.","example":"ends_with_any_hashed"},"list_id":{"type":"string","format":"uuid","description":"The list id (as in `values.list_id`)."},"values":{"nullable":true,"description":"The cleartext values; null when the list was sent pre-hashed and has no cleartext.","example":["@acme.test"],"type":"array","items":{"type":"string"}},"revealable":{"type":"boolean","description":"Whether the cleartext is available (false for pre-hashed lists).","example":true}},"required":["rule_index","condition_index","attribute","comparator","list_id","values","revealable"],"x-pc-sdk-model":"ConfidentialList"},"ConfidentialRevealResponseDto":{"type":"object","properties":{"data":{"description":"Every confidential list, in rule and condition order.","type":"array","items":{"$ref":"#/components/schemas/ConfidentialListDto"}}},"required":["data"],"x-pc-sdk-model":"ConfidentialReveal"},"FlagsSettingType":{"type":"string","enum":["boolean","string","integer","number","json"]},"FlagsSettingLifecycle":{"type":"string","enum":["temporary","permanent"]},"SettingResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The setting's id."},"workspace_id":{"type":"string","format":"uuid","description":"The workspace that owns it."},"project_id":{"type":"string","format":"uuid","description":"The project."},"config_id":{"type":"string","format":"uuid","description":"The config it belongs to."},"key":{"type":"string","description":"The key SDKs read it by; unique in the config, case-sensitive.","example":"new_checkout"},"name":{"type":"string","description":"Display name.","example":"New checkout"},"description":{"type":"string","description":"Free-text description (may be empty).","example":""},"hint":{"type":"string","description":"A short hint shown next to the flag in the console (may be empty).","example":""},"type":{"description":"`boolean` is a feature flag; the others are typed settings. Cannot change.","example":"boolean","allOf":[{"$ref":"#/components/schemas/FlagsSettingType"}]},"tags":{"description":"Free-form tags.","example":["checkout"],"type":"array","items":{"type":"string"}},"lifecycle":{"description":"`temporary` (a release flag you plan to remove) or `permanent` (an ops switch or a setting).","example":"temporary","allOf":[{"$ref":"#/components/schemas/FlagsSettingLifecycle"}]},"owner_id":{"type":"string","format":"uuid","nullable":true,"description":"The platform user who owns the flag (a workspace member), or null."},"seed":{"type":"string","description":"The value percentage splits hash with: the key at creation (or the ConfigCat key on import). It never changes, so renaming a key does not move users between variations.","example":"new_checkout"},"ordinal":{"type":"integer","description":"Sort position in the config (ascending).","example":0},"created_by":{"type":"string","nullable":true,"description":"Who created it (user or API key id)."},"created_at":{"type":"string","format":"date-time","description":"When it was created."},"updated_at":{"type":"string","format":"date-time","description":"When its metadata last changed."}},"required":["id","workspace_id","project_id","config_id","key","name","description","hint","type","tags","lifecycle","owner_id","seed","ordinal","created_by","created_at","updated_at"],"x-pc-sdk-model":"Setting"},"SettingListResponseDto":{"type":"object","properties":{"data":{"description":"Settings, in `ordinal` order.","type":"array","items":{"$ref":"#/components/schemas/SettingResponseDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/FlagsPaginationDto"}]}},"required":["data","pagination"],"x-pc-sdk-model":"SettingList"},"CreateSettingDto":{"type":"object","properties":{"key":{"type":"string","description":"The key SDKs read it by, unique in the config; must start with a letter and contain only letters, digits, \"_\", \".\" and \"-\", at most 128 characters.","example":"new_checkout"},"name":{"type":"string","description":"Display name, 1-200 characters. Defaults to the key.","example":"New checkout"},"type":{"description":"`boolean` for a feature flag; `string`, `integer`, `number` or `json` for a setting. Cannot change later.","example":"boolean","allOf":[{"$ref":"#/components/schemas/FlagsSettingType"}]},"description":{"type":"string","description":"Free-text description, at most 1000 characters."},"hint":{"type":"string","description":"Short hint, at most 500 characters."},"tags":{"description":"Tags, at most 20, each 1-50 characters.","example":["checkout"],"type":"array","items":{"type":"string"}},"lifecycle":{"default":"temporary","description":"Defaults to `temporary`.","allOf":[{"$ref":"#/components/schemas/FlagsSettingLifecycle"}]},"owner_id":{"type":"string","format":"uuid","nullable":true,"description":"A workspace member who owns the flag. Checked against the workspace members (422 `OWNER_NOT_A_MEMBER`)."},"initial_value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"description":"The value in every environment. Defaults to the type's zero: `false`, `\"\"`, `0`, `0`, `\"{}\"`. A non-zero value in a protected environment needs `flags.protected.update`. Must match the setting type: `boolean` true/false; `string` a string; `integer` a safe integer; `number` a finite number; `json` a string holding JSON text (for example `\"{\\\"limit\\\":5}\"`). At most 100 KB. Strings are stored and returned byte for byte.","example":false},"ordinal":{"type":"integer","description":"Sort position. Defaults to after the last one.","example":0},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"}},"required":["key","type"]},"FlagsSegmentComparator":{"type":"string","enum":["in","not_in"]},"SegmentConditionBodyDto":{"type":"object","properties":{"segment_id":{"type":"string","format":"uuid","description":"A segment of the same project (422 `SEGMENT_NOT_FOUND` otherwise)."},"comparator":{"description":"Whether the user must be in the segment or not in it.","allOf":[{"$ref":"#/components/schemas/FlagsSegmentComparator"}]}},"required":["segment_id","comparator"],"x-pc-sdk-model":"SegmentConditionBody"},"SegmentConditionDto":{"type":"object","properties":{"segment":{"description":"Require (or exclude) a segment.","allOf":[{"$ref":"#/components/schemas/SegmentConditionBodyDto"}]}},"required":["segment"],"x-pc-sdk-model":"SegmentCondition"},"FlagsPrerequisiteComparator":{"type":"string","enum":["eq","neq"]},"PrerequisiteConditionBodyDto":{"type":"object","properties":{"setting_id":{"type":"string","format":"uuid","description":"Another setting of the same config (not a json setting). Prerequisites must not form a cycle and chains are at most 16 deep."},"comparator":{"description":"Compare the prerequisite's evaluated value with `value`.","allOf":[{"$ref":"#/components/schemas/FlagsPrerequisiteComparator"}]},"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"description":"A value of the prerequisite setting's type.","example":true}},"required":["setting_id","comparator","value"],"x-pc-sdk-model":"PrerequisiteConditionBody"},"PrerequisiteConditionDto":{"type":"object","properties":{"prerequisite":{"description":"Depend on another flag's value for the same user.","allOf":[{"$ref":"#/components/schemas/PrerequisiteConditionBodyDto"}]}},"required":["prerequisite"],"x-pc-sdk-model":"PrerequisiteCondition"},"ServeRuleDto":{"type":"object","properties":{"conditions":{"type":"array","items":{"$ref":"#/components/schemas/TargetingCondition"},"description":"1-20 conditions, ANDed in order. Each condition is an object with exactly one of `user`, `segment`, `prerequisite`."},"serve":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"description":"Serve this value when every condition matches. Must match the setting type: `boolean` true/false; `string` a string; `integer` a safe integer; `number` a finite number; `json` a string holding JSON text (for example `\"{\\\"limit\\\":5}\"`). At most 100 KB. Strings are stored and returned byte for byte.","example":true}},"required":["conditions","serve"],"x-pc-sdk-model":"ServeRule"},"PercentageOptionDto":{"type":"object","properties":{"percentage":{"type":"integer","minimum":0,"maximum":100,"description":"Share of users, an integer; the options of one split add up to 100.","example":10},"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"description":"The value this share is served. Must match the setting type: `boolean` true/false; `string` a string; `integer` a safe integer; `number` a finite number; `json` a string holding JSON text (for example `\"{\\\"limit\\\":5}\"`). At most 100 KB. Strings are stored and returned byte for byte.","example":true}},"required":["percentage","value"],"x-pc-sdk-model":"PercentageOption"},"SplitRuleDto":{"type":"object","properties":{"conditions":{"type":"array","items":{"$ref":"#/components/schemas/TargetingCondition"},"description":"1-20 conditions, ANDed in order. Each condition is an object with exactly one of `user`, `segment`, `prerequisite`."},"percentages":{"description":"Split the matching users by a stable hash of the setting seed and the percentage attribute; integers adding up to 100.","type":"array","items":{"$ref":"#/components/schemas/PercentageOptionDto"}}},"required":["conditions","percentages"],"x-pc-sdk-model":"SplitRule"},"FlagsActorType":{"type":"string","enum":["user","api_key","system"]},"SettingUpdatedByDto":{"type":"object","properties":{"type":{"description":"Who wrote the value last.","allOf":[{"$ref":"#/components/schemas/FlagsActorType"}]},"id":{"type":"string","nullable":true,"description":"The user or API key id; null for system writes."}},"required":["type","id"],"x-pc-sdk-model":"SettingUpdatedBy"},"SettingValueResponseDto":{"type":"object","properties":{"setting_id":{"type":"string","format":"uuid","description":"The setting."},"environment_id":{"type":"string","format":"uuid","description":"The environment."},"environment_key":{"type":"string","description":"The environment's key.","example":"production"},"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"description":"Served when no rule and no split decides (and to everyone when there are none).","example":false},"rules":{"type":"array","items":{"$ref":"#/components/schemas/TargetingRule"},"description":"Targeting rules, first match wins (at most 50). Each rule has `conditions` and exactly one of `serve` (a value) or `percentages` (a split)."},"percentages":{"nullable":true,"description":"Flag-level split after the rules (null for none).","type":"array","items":{"$ref":"#/components/schemas/PercentageOptionDto"}},"percentage_attribute":{"type":"string","nullable":true,"description":"The user attribute the splits hash; null means `identifier`.","example":null},"version":{"type":"integer","description":"Send it back with the next write; a stale one answers 409 `VERSION_CONFLICT`.","example":3},"updated_by":{"nullable":true,"description":"Who wrote the value last.","allOf":[{"$ref":"#/components/schemas/SettingUpdatedByDto"}]},"updated_at":{"type":"string","format":"date-time","description":"When the value last changed."}},"required":["setting_id","environment_id","environment_key","value","rules","percentages","percentage_attribute","version","updated_by","updated_at"],"x-pc-sdk-model":"SettingValue"},"SettingDependentDto":{"type":"object","properties":{"setting_id":{"type":"string","format":"uuid","description":"The setting that uses this one as a prerequisite."},"setting_key":{"type":"string","description":"That setting's key.","example":"new_checkout"},"environment_id":{"type":"string","format":"uuid","description":"The environment where it does."},"environment_key":{"type":"string","description":"The environment's key.","example":"production"}},"required":["setting_id","setting_key","environment_id","environment_key"],"x-pc-sdk-model":"SettingDependent"},"SettingDependentsDto":{"type":"object","properties":{"prerequisite_of":{"description":"Settings whose rules use this one as a prerequisite, per environment. A setting listed here cannot be deleted.","type":"array","items":{"$ref":"#/components/schemas/SettingDependentDto"}},"segments_used":{"description":"Keys of the segments its rules use, in any environment.","example":["qa_staff"],"type":"array","items":{"type":"string"}}},"required":["prerequisite_of","segments_used"],"x-pc-sdk-model":"SettingDependents"},"SettingDetailResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The setting's id."},"workspace_id":{"type":"string","format":"uuid","description":"The workspace that owns it."},"project_id":{"type":"string","format":"uuid","description":"The project."},"config_id":{"type":"string","format":"uuid","description":"The config it belongs to."},"key":{"type":"string","description":"The key SDKs read it by; unique in the config, case-sensitive.","example":"new_checkout"},"name":{"type":"string","description":"Display name.","example":"New checkout"},"description":{"type":"string","description":"Free-text description (may be empty).","example":""},"hint":{"type":"string","description":"A short hint shown next to the flag in the console (may be empty).","example":""},"type":{"description":"`boolean` is a feature flag; the others are typed settings. Cannot change.","example":"boolean","allOf":[{"$ref":"#/components/schemas/FlagsSettingType"}]},"tags":{"description":"Free-form tags.","example":["checkout"],"type":"array","items":{"type":"string"}},"lifecycle":{"description":"`temporary` (a release flag you plan to remove) or `permanent` (an ops switch or a setting).","example":"temporary","allOf":[{"$ref":"#/components/schemas/FlagsSettingLifecycle"}]},"owner_id":{"type":"string","format":"uuid","nullable":true,"description":"The platform user who owns the flag (a workspace member), or null."},"seed":{"type":"string","description":"The value percentage splits hash with: the key at creation (or the ConfigCat key on import). It never changes, so renaming a key does not move users between variations.","example":"new_checkout"},"ordinal":{"type":"integer","description":"Sort position in the config (ascending).","example":0},"created_by":{"type":"string","nullable":true,"description":"Who created it (user or API key id)."},"created_at":{"type":"string","format":"date-time","description":"When it was created."},"updated_at":{"type":"string","format":"date-time","description":"When its metadata last changed."},"values":{"description":"Its value and targeting in every environment, in environment order.","type":"array","items":{"$ref":"#/components/schemas/SettingValueResponseDto"}},"dependents":{"description":"What depends on this setting: check before deleting or renaming it.","allOf":[{"$ref":"#/components/schemas/SettingDependentsDto"}]}},"required":["id","workspace_id","project_id","config_id","key","name","description","hint","type","tags","lifecycle","owner_id","seed","ordinal","created_by","created_at","updated_at","values","dependents"],"x-pc-sdk-model":"SettingDetail"},"SettingStateDto":{"type":"object","properties":{"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"description":"The plain value in that environment.","example":true},"has_rules":{"type":"boolean","description":"Whether that environment has rules or a split.","example":false}},"required":["value","has_rules"],"x-pc-sdk-model":"SettingState"},"EnvironmentValueRowDto":{"type":"object","properties":{"setting":{"description":"The setting.","allOf":[{"$ref":"#/components/schemas/SettingResponseDto"}]},"value":{"description":"Its value and targeting in this environment.","allOf":[{"$ref":"#/components/schemas/SettingValueResponseDto"}]},"states":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SettingStateDto"},"description":"With `include=states`: the compact state in every environment of the project, keyed by environment key (the mini state column).","example":{"development":{"value":true,"has_rules":false},"production":{"value":false,"has_rules":true}}}},"required":["setting","value"],"x-pc-sdk-model":"EnvironmentValueRow"},"EnvironmentValueListResponseDto":{"type":"object","properties":{"data":{"description":"Settings of the config with their value in this environment, in `ordinal` order.","type":"array","items":{"$ref":"#/components/schemas/EnvironmentValueRowDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/FlagsPaginationDto"}]}},"required":["data","pagination"],"x-pc-sdk-model":"EnvironmentValueList"},"CompareEnvironmentDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The environment."},"key":{"type":"string","description":"Its key.","example":"production"},"name":{"type":"string","description":"Its name.","example":"Production"}},"required":["id","key","name"],"x-pc-sdk-model":"CompareEnvironment"},"CompareRowDto":{"type":"object","properties":{"setting":{"description":"The setting.","allOf":[{"$ref":"#/components/schemas/SettingResponseDto"}]},"values":{"description":"Its value in each requested environment, in the order of `environment_ids`.","type":"array","items":{"$ref":"#/components/schemas/SettingValueResponseDto"}},"differs":{"type":"boolean","description":"Whether the environments differ in value or targeting.","example":true}},"required":["setting","values","differs"],"x-pc-sdk-model":"CompareRow"},"CompareResponseDto":{"type":"object","properties":{"environments":{"description":"The compared environments, in request order.","type":"array","items":{"$ref":"#/components/schemas/CompareEnvironmentDto"}},"data":{"description":"One row per setting, in `ordinal` order.","type":"array","items":{"$ref":"#/components/schemas/CompareRowDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/FlagsPaginationDto"}]}},"required":["environments","data","pagination"],"x-pc-sdk-model":"Compare"},"UpdateSettingDto":{"type":"object","properties":{"key":{"type":"string","description":"New key; must start with a letter and contain only letters, digits, \"_\", \".\" and \"-\", at most 128 characters. SDK code reading the old key gets its default, so check `dependents` and your code first. Needs `flags.protected.update` when the project has a protected environment. The seed does not change.","example":"new_checkout_v2"},"name":{"type":"string","description":"Display name, 1-200 characters."},"description":{"type":"string","description":"Free-text description, at most 1000 characters."},"hint":{"type":"string","description":"Short hint, at most 500 characters."},"tags":{"description":"Replaces the tags: at most 20, each 1-50 characters.","type":"array","items":{"type":"string"}},"lifecycle":{"description":"`temporary` or `permanent`.","allOf":[{"$ref":"#/components/schemas/FlagsSettingLifecycle"}]},"owner_id":{"type":"string","format":"uuid","nullable":true,"description":"A workspace member, or null to clear."},"ordinal":{"type":"integer","description":"Sort position."},"type":{"description":"Cannot change: sending a type other than the current one answers 422 `SETTING_TYPE_IMMUTABLE`.","allOf":[{"$ref":"#/components/schemas/FlagsSettingType"}]},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"}}},"PutSettingValueDto":{"type":"object","properties":{"version":{"type":"integer","minimum":1,"description":"The `version` you read; 409 `VERSION_CONFLICT` when it moved.","example":3},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"},"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"description":"Served when no rule and no split decides. Must match the setting type: `boolean` true/false; `string` a string; `integer` a safe integer; `number` a finite number; `json` a string holding JSON text (for example `\"{\\\"limit\\\":5}\"`). At most 100 KB. Strings are stored and returned byte for byte.","example":false},"rules":{"type":"array","items":{"$ref":"#/components/schemas/TargetingRule"},"description":"Targeting rules, first match wins (at most 50). Each rule has `conditions` and exactly one of `serve` (a value) or `percentages` (a split). Omitted = none."},"percentages":{"nullable":true,"description":"Flag-level split after the rules; null or omitted for none.","type":"array","items":{"$ref":"#/components/schemas/PercentageOptionDto"}},"percentage_attribute":{"type":"string","nullable":true,"description":"The user attribute splits hash (1-256 characters, returned exactly as sent); null or omitted for `identifier`.","example":null}},"required":["version","value"]},"PatchSettingValueDto":{"type":"object","properties":{"version":{"type":"integer","minimum":1,"description":"The `version` you read; 409 `VERSION_CONFLICT` when it moved.","example":3},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Ticket FLAG-142"},"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"description":"The new plain value (the on/off toggle for a flag). Must match the setting type: `boolean` true/false; `string` a string; `integer` a safe integer; `number` a finite number; `json` a string holding JSON text (for example `\"{\\\"limit\\\":5}\"`). At most 100 KB. Strings are stored and returned byte for byte.","example":true},"percentage_attribute":{"type":"string","nullable":true,"description":"The attribute splits hash; null for `identifier`."},"clear_rules":{"type":"boolean","description":"Remove every rule and the flag-level split, so `value` is served to everyone (the kill switch). Restore the targeting from the history if needed.","example":false}},"required":["version"]},"SdkKeySlot":{"type":"string","enum":["primary","secondary"]},"SdkKeyResponseDto":{"type":"object","properties":{"slot":{"description":"`primary` is the current key; `secondary` is the previous one during a rotation's grace period.","allOf":[{"$ref":"#/components/schemas/SdkKeySlot"}]},"key_prefix":{"type":"string","description":"The first 12 characters of the key.","example":"pcf_sdk_4fQx"},"last4":{"type":"string","description":"The last 4 characters of the key.","example":"k9Zt"},"created_at":{"type":"string","format":"date-time","description":"When the key was minted."},"expires_at":{"type":"string","format":"date-time","nullable":true,"description":"Secondary keys only: when the key stops resolving (end of the grace period). `null` for the primary key."}},"required":["slot","key_prefix","last4","created_at","expires_at"],"x-pc-sdk-model":"SdkKey"},"SdkKeyListResponseDto":{"type":"object","properties":{"data":{"description":"The primary key, then the secondary key while a grace period runs.","type":"array","items":{"$ref":"#/components/schemas/SdkKeyResponseDto"}}},"required":["data"],"x-pc-sdk-model":"SdkKeyList"},"RevealedSdkKeyDto":{"type":"object","properties":{"slot":{"description":"`primary` is the current key; `secondary` is the previous one during a rotation's grace period.","allOf":[{"$ref":"#/components/schemas/SdkKeySlot"}]},"key_prefix":{"type":"string","description":"The first 12 characters of the key.","example":"pcf_sdk_4fQx"},"last4":{"type":"string","description":"The last 4 characters of the key.","example":"k9Zt"},"created_at":{"type":"string","format":"date-time","description":"When the key was minted."},"expires_at":{"type":"string","format":"date-time","nullable":true,"description":"Secondary keys only: when the key stops resolving (end of the grace period). `null` for the primary key."},"key":{"type":"string","description":"The full SDK key (`pcf_sdk_` + 38 characters). A read credential for this config in this environment: keep it server-side unless the config is meant for browsers or mobile apps.","example":"pcf_sdk_4fQxV2mB8cJ0nR7tW1yZ3aD5gH6kL9pS0q1Uk9Zt"}},"required":["slot","key_prefix","last4","created_at","expires_at","key"],"x-pc-sdk-model":"RevealedSdkKey"},"RevealedSdkKeyListResponseDto":{"type":"object","properties":{"data":{"description":"The primary key, then the secondary key while a grace period runs.","type":"array","items":{"$ref":"#/components/schemas/RevealedSdkKeyDto"}}},"required":["data"],"x-pc-sdk-model":"RevealedSdkKeyList"},"RotateSdkKeyDto":{"type":"object","properties":{"grace_hours":{"type":"integer","minimum":0,"maximum":168,"default":24,"description":"How long the current key keeps working as the secondary key, in hours (0 to 168). `0` revokes it at once. An existing secondary key is revoked by the rotation."},"note":{"type":"string","maxLength":500,"description":"Why, recorded in the history."}}},"EvaluateRequestDto":{"type":"object","properties":{"user":{"type":"object","additionalProperties":true,"nullable":true,"description":"The user to evaluate for, in the SDK's shape: `identifier`, `email`, `country` and `custom: {…}`; flat attributes are accepted too (`custom` wins when both name one). Attribute names are yours and kept as sent. `null` or omitted: no user (rules that need one are soft misses with `missing_user`). Attribute values are text, numbers, booleans or arrays of text; anything else is a soft miss (`invalid_attribute`), as in the SDKs. Dates: send unix seconds, `{\"$date\": \"<ISO 8601>\"}`, or a plain ISO 8601 string for an attribute that a `before`/`after` condition of this config uses (converted to unix seconds; a console convenience, SDKs take a `Date` or unix seconds). Never stored or logged.","example":{"identifier":"user-2","email":"ada@acme.com","custom":{"app_version":"2.1.0"}}},"keys":{"maxItems":200,"description":"Setting keys to evaluate (at most 200). Omitted: every setting. An unknown key returns a `FLAG_NOT_FOUND` row.","example":["new_checkout","banner_text"],"type":"array","items":{"type":"string"}},"revision":{"type":"integer","minimum":1,"description":"Evaluate this published revision instead of the current one (404 `REVISION_NOT_FOUND` once pruned).","example":41}}},"FlagsEvaluationReason":{"type":"string","enum":["STATIC","TARGETING_MATCH","SPLIT","DEFAULT","ERROR"]},"FlagsEvaluationErrorCode":{"type":"string","enum":["FLAG_NOT_FOUND","TYPE_MISMATCH","PREREQUISITE_CYCLE","PREREQUISITE_NOT_FOUND","PREREQUISITE_DEPTH","GENERAL"]},"FlagsEvaluationWarningCode":{"type":"string","enum":["missing_user","missing_attribute","invalid_attribute","unknown_comparator","missing_percentage_attribute"]},"EvaluationWarningDto":{"type":"object","properties":{"code":{"description":"Stable warning code: a condition or split could not be evaluated for this user, and evaluation went on (a soft miss).","example":"missing_attribute","allOf":[{"$ref":"#/components/schemas/FlagsEvaluationWarningCode"}]},"message":{"type":"string","description":"Human-readable explanation.","example":"The user has no attribute \"app_version\"."},"key":{"type":"string","description":"The setting being evaluated when the warning was recorded (a prerequisite's key for its own warnings).","example":"new_checkout"},"rule_index":{"type":"integer","nullable":true,"description":"The rule the warning comes from, or `null` for the flag-level split.","example":1},"attribute":{"type":"string","nullable":true,"description":"The user attribute involved, when there is one.","example":"app_version"}},"required":["code","message","key","rule_index","attribute"],"x-pc-sdk-model":"EvaluationWarning"},"EvaluationResultDto":{"type":"object","properties":{"key":{"type":"string","description":"The setting key.","example":"new_checkout"},"value":{"oneOf":[{"type":"boolean"},{"type":"string"},{"type":"number"}],"nullable":true,"description":"The value an SDK would serve this user. `json` settings serve their JSON text. On `ERROR` it is the default: the setting's own value, or `null` for an unknown key.","example":true},"variant":{"type":"string","nullable":true,"description":"`rule:i`, `rule:i/pct:j`, `pct:j` or `default` (the setting's own value); `null` on `ERROR`.","example":"rule:1/pct:0"},"reason":{"description":"Why this value: `STATIC` (no targeting), `TARGETING_MATCH` (a rule served it), `SPLIT` (a percentage option), `DEFAULT` (targeting exists, nothing matched), `ERROR` (see `error_code`).","example":"SPLIT","allOf":[{"$ref":"#/components/schemas/FlagsEvaluationReason"}]},"error_code":{"nullable":true,"description":"Set when `reason` is `ERROR`. `FLAG_NOT_FOUND`: no setting with this key in the revision.","example":null,"allOf":[{"$ref":"#/components/schemas/FlagsEvaluationErrorCode"}]},"error_message":{"type":"string","nullable":true,"description":"Explanation of `error_code`.","example":null},"rule_index":{"type":"integer","nullable":true,"description":"Index of the rule that decided, from 0.","example":1},"percentage_index":{"type":"integer","nullable":true,"description":"Index of the percentage option that decided, from 0.","example":0},"is_default_value":{"type":"boolean","description":"True only when the default was returned because of an error.","example":false},"warnings":{"description":"Soft misses recorded while evaluating, in order.","type":"array","items":{"$ref":"#/components/schemas/EvaluationWarningDto"}}},"required":["key","value","variant","reason","error_code","error_message","rule_index","percentage_index","is_default_value","warnings"],"x-pc-sdk-model":"EvaluationResult"},"TestEvaluationResponseDto":{"type":"object","properties":{"revision":{"type":"integer","description":"The config revision evaluated.","example":42},"data":{"description":"One row per evaluated key: the requested keys in request order, or every setting in config order.","type":"array","items":{"$ref":"#/components/schemas/EvaluationResultDto"}}},"required":["revision","data"],"x-pc-sdk-model":"TestEvaluation"},"FlagsChangeActorType":{"type":"string","enum":["user","api_key","system"]},"ChangeActorDto":{"type":"object","properties":{"type":{"description":"Who made the change: a signed-in user (also through an OAuth client or MCP), an API key, or Flags itself.","allOf":[{"$ref":"#/components/schemas/FlagsChangeActorType"}]},"id":{"type":"string","nullable":true,"description":"The platform user id or API key id; null for `system`."},"label":{"type":"string","nullable":true,"description":"The user's email or the key's name when the change was made.","example":"ada@example.com"},"on_behalf_of_user_id":{"type":"string","format":"uuid","nullable":true,"description":"The user an OAuth client or MCP connection acted for, when it was one."},"client_id":{"type":"string","nullable":true,"description":"The OAuth / MCP client id, when the change came through one."}},"required":["type","id","label","on_behalf_of_user_id","client_id"],"x-pc-sdk-model":"ChangeActor"},"ChangeRevisionDto":{"type":"object","properties":{"config_id":{"type":"string","format":"uuid","description":"The config."},"environment_id":{"type":"string","format":"uuid","description":"The environment."},"revision":{"type":"integer","description":"The config revision the change published there.","example":7},"url":{"type":"string","format":"uri","description":"The revision as SDKs downloaded it (`GET …/revisions/{revision}`).","example":"https://api.flags.productcraft.co/v1/workspaces/9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b/configs/1f0c…/environments/7a2e…/revisions/7"},"previous_url":{"type":"string","format":"uri","nullable":true,"description":"The revision before it (null for revision 1). It may have been pruned (the last 100 are kept)."}},"required":["config_id","environment_id","revision","url","previous_url"],"x-pc-sdk-model":"ChangeRevision"},"ChangeResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Id of the change."},"project_id":{"type":"string","format":"uuid","description":"The project."},"config_id":{"type":"string","format":"uuid","nullable":true,"description":"The config, for changes of a config, its settings, values or SDK keys."},"environment_id":{"type":"string","format":"uuid","nullable":true,"description":"The environment, for value writes and SDK key changes."},"entity_type":{"type":"string","description":"What changed: `project`, `environment`, `config`, `setting`, `setting_value`, `segment` or `sdk_key` (open: more may come).","example":"setting_value"},"entity_id":{"type":"string","format":"uuid","description":"Id of the entity (for `setting_value`, the setting).","example":"5b1f0c2e-8d4a-4e6b-9f3a-1c2d3e4f5a6b"},"entity_key":{"type":"string","nullable":true,"description":"The key of the entity at the time (an environment key for SDK keys).","example":"new_checkout"},"action":{"type":"string","description":"`<entity>.<verb>`, e.g. `setting_value.updated`, `setting.created`, `segment.deleted`, `sdk_key.rotated`, `confidential.revealed` (open: more may come).","example":"setting_value.updated"},"actor":{"description":"Who made the change.","allOf":[{"$ref":"#/components/schemas/ChangeActorDto"}]},"note":{"type":"string","nullable":true,"description":"The note sent with the write.","example":"Ticket FLAG-142"},"revisions":{"description":"Config revisions the change published (empty when it changed nothing SDKs download).","type":"array","items":{"$ref":"#/components/schemas/ChangeRevisionDto"}},"reverts_change_id":{"type":"string","format":"uuid","nullable":true,"description":"The change this one restored (`POST …/changes/{id}/revert`)."},"summary":{"description":"Human-readable lines, e.g. \"Production: value false → true\" or \"rule 2 percentage 10 → 25\". Confidential lists show as counts (\"+3 / −1 values\"), never values. Empty when the change is too large to summarise (`diff_too_large`).","example":["Production: value false → true"],"type":"array","items":{"type":"string"}},"diff_too_large":{"type":"boolean","description":"Whether `before` and `after` together exceed 64 KB: then there is no diff and no summary; compare the two revisions instead."},"size_bytes":{"type":"integer","description":"Bytes `before` and `after` take up in history storage (they count toward the 200 MiB per project)."},"created_at":{"type":"string","format":"date-time","description":"When the change was made."}},"required":["id","project_id","config_id","environment_id","entity_type","entity_id","entity_key","action","actor","note","revisions","reverts_change_id","summary","diff_too_large","size_bytes","created_at"],"x-pc-sdk-model":"Change"},"ChangeListResponseDto":{"type":"object","properties":{"data":{"description":"Changes, newest first.","type":"array","items":{"$ref":"#/components/schemas/ChangeResponseDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/FlagsPaginationDto"}]}},"required":["data","pagination"],"x-pc-sdk-model":"ChangeList"},"FlagsHistoryExportFormat":{"type":"string","enum":["csv","json"]},"FlagsJsonPatchOp":{"type":"string","enum":["add","remove","replace"]},"JsonPatchOperationDto":{"type":"object","properties":{"op":{"description":"RFC 6902 operation.","allOf":[{"$ref":"#/components/schemas/FlagsJsonPatchOp"}]},"path":{"type":"string","description":"JSON Pointer (RFC 6901) into `before`.","example":"/rules/1/percentages/0/percentage"},"value":{"description":"The new value (`add`, `replace`): any JSON value.","example":25}},"required":["op","path"],"x-pc-sdk-model":"JsonPatchOperation"},"ChangeDetailResponseDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Id of the change."},"project_id":{"type":"string","format":"uuid","description":"The project."},"config_id":{"type":"string","format":"uuid","nullable":true,"description":"The config, for changes of a config, its settings, values or SDK keys."},"environment_id":{"type":"string","format":"uuid","nullable":true,"description":"The environment, for value writes and SDK key changes."},"entity_type":{"type":"string","description":"What changed: `project`, `environment`, `config`, `setting`, `setting_value`, `segment` or `sdk_key` (open: more may come).","example":"setting_value"},"entity_id":{"type":"string","format":"uuid","description":"Id of the entity (for `setting_value`, the setting).","example":"5b1f0c2e-8d4a-4e6b-9f3a-1c2d3e4f5a6b"},"entity_key":{"type":"string","nullable":true,"description":"The key of the entity at the time (an environment key for SDK keys).","example":"new_checkout"},"action":{"type":"string","description":"`<entity>.<verb>`, e.g. `setting_value.updated`, `setting.created`, `segment.deleted`, `sdk_key.rotated`, `confidential.revealed` (open: more may come).","example":"setting_value.updated"},"actor":{"description":"Who made the change.","allOf":[{"$ref":"#/components/schemas/ChangeActorDto"}]},"note":{"type":"string","nullable":true,"description":"The note sent with the write.","example":"Ticket FLAG-142"},"revisions":{"description":"Config revisions the change published (empty when it changed nothing SDKs download).","type":"array","items":{"$ref":"#/components/schemas/ChangeRevisionDto"}},"reverts_change_id":{"type":"string","format":"uuid","nullable":true,"description":"The change this one restored (`POST …/changes/{id}/revert`)."},"summary":{"description":"Human-readable lines, e.g. \"Production: value false → true\" or \"rule 2 percentage 10 → 25\". Confidential lists show as counts (\"+3 / −1 values\"), never values. Empty when the change is too large to summarise (`diff_too_large`).","example":["Production: value false → true"],"type":"array","items":{"type":"string"}},"diff_too_large":{"type":"boolean","description":"Whether `before` and `after` together exceed 64 KB: then there is no diff and no summary; compare the two revisions instead."},"size_bytes":{"type":"integer","description":"Bytes `before` and `after` take up in history storage (they count toward the 200 MiB per project)."},"created_at":{"type":"string","format":"date-time","description":"When the change was made."},"before":{"type":"object","additionalProperties":true,"nullable":true,"description":"The entity before the change (null for a create). Confidential lists show as `{hashed, count, list_id, editable}`, never values. Null when `diff_too_large`: read the revisions instead."},"after":{"type":"object","additionalProperties":true,"nullable":true,"description":"The entity after the change (null for a delete), in the same form as `before`. Null when `diff_too_large`."},"diff":{"nullable":true,"description":"JSON Patch (RFC 6902) from `before` to `after`. Null when `diff_too_large`.","type":"array","items":{"$ref":"#/components/schemas/JsonPatchOperationDto"}}},"required":["id","project_id","config_id","environment_id","entity_type","entity_id","entity_key","action","actor","note","revisions","reverts_change_id","summary","diff_too_large","size_bytes","created_at","before","after","diff"],"x-pc-sdk-model":"ChangeDetail"},"RevertChangeDto":{"type":"object","properties":{"version":{"type":"integer","minimum":1,"description":"The current `version` of the entity (the setting value or the segment) you are restoring over; 409 `VERSION_CONFLICT` when it moved. Settings have no version: for `setting.updated` it is ignored and the restore is refused with 409 when the setting no longer matches the change's `after`.","example":4},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the new history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Roll back FLAG-142"}}},"CopyEnvironmentDto":{"type":"object","properties":{"source_environment_id":{"type":"string","format":"uuid","description":"The environment to copy targeting from (same project)."},"setting_ids":{"description":"The settings to copy (at most 500). Send this or `all_differing: true`.","type":"array","items":{"type":"string","format":"uuid"}},"all_differing":{"type":"boolean","description":"Copy every setting whose value or targeting differs between the two environments. Send this or `setting_ids`.","example":true},"versions":{"type":"object","additionalProperties":{"type":"integer","minimum":1},"description":"The target environment's current `version` of every setting that will be copied, by setting id. If any is stale or missing, nothing is written and 409 `VERSION_CONFLICT` lists every one (`details.conflicts`).","example":{"0b8f8a2c-4d3e-4f5a-8b6c-7d8e9f0a1b2c":3}},"note":{"type":"string","description":"A change note (at most 500 characters), saved on the new history entry. Environments with `require_note` refuse value writes without one.","maxLength":500,"example":"Roll back FLAG-142"}},"required":["source_environment_id","versions"]},"CopiedSettingDto":{"type":"object","properties":{"setting_id":{"type":"string","format":"uuid","description":"The setting."},"key":{"type":"string","description":"Its key.","example":"new_checkout"},"version":{"type":"integer","description":"Its new `version` in the target environment.","example":4},"change_id":{"type":"string","format":"uuid","description":"The history entry of this setting's copy."}},"required":["setting_id","key","version","change_id"],"x-pc-sdk-model":"CopiedSetting"},"CopyEnvironmentResponseDto":{"type":"object","properties":{"data":{"description":"The settings whose targeting was copied (empty when nothing differed).","type":"array","items":{"$ref":"#/components/schemas/CopiedSettingDto"}},"revision":{"type":"integer","nullable":true,"description":"The config revision the copy published in the target environment (null when nothing changed).","example":12}},"required":["data","revision"],"x-pc-sdk-model":"CopyEnvironment"},"FlagsWebhookProjectDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"3c9d2f4e-1a2b-4c3d-8e9f-0a1b2c3d4e5f","description":"The project id."},"name":{"type":"string","example":"Storefront","description":"The project name when the event was sent."}},"required":["id","name"],"x-pc-sdk-model":"FlagsWebhookProject"},"FlagsWebhookConfigDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"1f0c8b7a-6d5e-4f3a-9b2c-1d0e9f8a7b6c","description":"The config id."},"key":{"type":"string","example":"main","description":"The config key."},"name":{"type":"string","example":"Main","description":"The config name."}},"required":["id","key","name"],"x-pc-sdk-model":"FlagsWebhookConfig"},"FlagsWebhookEnvironmentDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"7a2e4c6d-8f0a-4b1c-9d3e-5f7a9b1c3d5e","description":"The environment id."},"key":{"type":"string","example":"production","description":"The environment key."},"name":{"type":"string","example":"Production","description":"The environment name."}},"required":["id","key","name"],"x-pc-sdk-model":"FlagsWebhookEnvironment"},"FlagsWebhookActorType":{"type":"string","enum":["user","api_key","system"]},"FlagsWebhookActorDto":{"type":"object","properties":{"type":{"example":"user","description":"A signed-in user (also through an OAuth client or MCP), an API key, or Flags itself.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookActorType"}]},"id":{"type":"string","nullable":true,"example":"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9","description":"The user or API key id; null for `system`."},"label":{"type":"string","nullable":true,"example":"ada@example.com","description":"The user's email or the key's name."}},"required":["type","id","label"],"x-pc-sdk-model":"FlagsWebhookActor"},"FlagsWebhookChangeDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","nullable":true,"example":"0d1e2f3a-4b5c-4d6e-8f7a-9b0c1d2e3f4a","description":"The history entry of the write (`GET /v1/workspaces/{workspace_id}/changes/{change_id}`); null if it has been pruned."},"action":{"type":"string","nullable":true,"example":"setting_value.updated","description":"What the write did, `<entity>.<verb>`."},"note":{"type":"string","nullable":true,"example":"Ticket FLAG-142","description":"The note sent with the write."},"actor":{"nullable":true,"description":"Who made the write.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookActorDto"}]}},"required":["id","action","note","actor"],"x-pc-sdk-model":"FlagsWebhookChange"},"ConfigPublishedEventDataDto":{"type":"object","properties":{"project":{"description":"The project.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookProjectDto"}]},"config":{"description":"The config that was published.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookConfigDto"}]},"environment":{"description":"The environment it was published in.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookEnvironmentDto"}]},"revision":{"type":"integer","example":13,"description":"The new revision SDKs download now."},"previous_revision":{"type":"integer","example":12,"description":"The revision it replaced (0 for the first one)."},"generation":{"type":"integer","example":1,"description":"The generation of the config; it changes only after a database restore. Order events by `generation`, then `revision`."},"etag":{"type":"string","example":"q8w4Yb0cJ0dY2t1vUo3n7A","description":"The ETag SDKs see for this revision."},"published_at":{"type":"string","format":"date-time","example":"2026-11-09T10:00:00.000Z","description":"When the revision was published."},"change":{"description":"The write that published it.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookChangeDto"}]},"settings_changed":{"example":["new_checkout"],"description":"Keys of the settings whose served value or targeting changed in this revision (removed ones included).","type":"array","items":{"type":"string"}}},"required":["project","config","environment","revision","previous_revision","generation","etag","published_at","change","settings_changed"],"x-pc-sdk-model":"ConfigPublishedEventData"},"FlagsSdkKeyRotationReason":{"type":"string","enum":["rotated","grace_ended"]},"FlagsSdkKeySlot":{"type":"string","enum":["primary","secondary"]},"SdkKeyRotatedEventDataDto":{"type":"object","properties":{"project":{"description":"The project.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookProjectDto"}]},"config":{"description":"The config the key belongs to.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookConfigDto"}]},"environment":{"description":"The environment the key belongs to.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookEnvironmentDto"}]},"reason":{"example":"rotated","description":"`rotated`: a new primary key was made. `grace_ended`: the previous key stopped working before its grace period ran out.","allOf":[{"$ref":"#/components/schemas/FlagsSdkKeyRotationReason"}]},"slot":{"example":"primary","description":"The slot this event is about: the new `primary` on a rotation, the ended `secondary` when a grace period ends.","allOf":[{"$ref":"#/components/schemas/FlagsSdkKeySlot"}]},"key_prefix":{"type":"string","example":"pcf_sdk_8kQz","description":"The first 12 characters of that key (never the key itself)."},"expires_at":{"type":"string","format":"date-time","nullable":true,"example":"2026-11-10T10:00:00.000Z","description":"When the previous key stops working: the end of the grace period on a rotation (null if it stopped at once), the time it ended on `grace_ended`."},"change":{"description":"The history entry of the rotation.","allOf":[{"$ref":"#/components/schemas/FlagsWebhookChangeDto"}]}},"required":["project","config","environment","reason","slot","key_prefix","expires_at","change"],"x-pc-sdk-model":"SdkKeyRotatedEventData"},"WebhookEventType":{"type":"string","enum":["config.published","sdk_key.rotated"],"description":"Every event type this product sends; `x-webhooks` maps each to its payload schema. New types can be added, so treat it as open."},"WebhookEventTypeDto":{"type":"object","properties":{"type":{"example":"config.published","description":"The event type (one of this product's catalogue).","allOf":[{"$ref":"#/components/schemas/WebhookEventType"}]},"description":{"type":"string","example":"A user signed up or was created by an admin.","description":"When this event is sent."},"category":{"type":"string","example":"Users","description":"Group shown in the event picker."},"example":{"type":"object","additionalProperties":true,"description":"An example `data` object; \"Send test\" delivers exactly this."}},"x-pc-sdk-model":"WebhookEventTypeInfo","required":["type","description","category","example"]},"ListWebhookEventTypesResponseDto":{"type":"object","properties":{"data":{"description":"Every event type this product sends.","type":"array","items":{"$ref":"#/components/schemas/WebhookEventTypeDto"}}},"x-pc-sdk-model":"WebhookEventTypeList","x-pc-sdk-model-aliases":["ListWebhookEventTypes"],"required":["data"]},"WebhookEndpointStatus":{"type":"string","enum":["enabled","disabled","auto_disabled"]},"WebhookEndpointDisabledReason":{"type":"string","enum":["manual","failing"]},"WebhookEndpointDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The endpoint's id."},"scope_type":{"type":"string","example":"workspace","description":"What owns the endpoint: `workspace`, `app` or `community`."},"scope_id":{"type":"string","description":"Id of the owning workspace, app or community."},"url":{"type":"string","format":"uri","example":"https://api.acme.com/webhooks","description":"Where events are sent."},"description":{"type":"string","nullable":true,"example":"Production receiver","description":"A label for people; null when unset."},"event_types":{"description":"Subscribed event types. Empty means every event, including types added later.","example":[],"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean","description":"The on/off switch (`PATCH … { enabled }`)."},"status":{"description":"`enabled` receives events. `disabled` was switched off. `auto_disabled` was switched off after 20 failed deliveries in a row or 24 hours of failures; `PATCH { enabled: true }` turns it back on.","allOf":[{"$ref":"#/components/schemas/WebhookEndpointStatus"}]},"disabled_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was switched off; null while enabled."},"disabled_reason":{"nullable":true,"description":"`manual`: switched off by a caller. `failing`: switched off automatically after failed deliveries. Null while enabled.","allOf":[{"$ref":"#/components/schemas/WebhookEndpointDisabledReason"}]},"consecutive_failures":{"type":"number","description":"Failed automatic deliveries in a row; a success resets it."},"first_failure_at":{"type":"string","format":"date-time","nullable":true,"description":"Start of the current failure streak."},"signing_secret_hint":{"type":"string","description":"Last 4 characters of the signing secret.","example":"x9Q="},"prev_signing_secret_active":{"type":"boolean","description":"True while the previous secret still signs too (after a rotation, for its grace period)."},"prev_signing_secret_expires_at":{"type":"string","format":"date-time","nullable":true,"description":"Until then the previous secret signs too (after a rotation)."},"legacy_signature":{"type":"boolean","description":"True for endpoints carried over from the product's previous webhook system: they also receive the old signature header until its sunset date."},"created_at":{"type":"string","format":"date-time","description":"When the endpoint was created."},"updated_at":{"type":"string","format":"date-time","description":"When the endpoint last changed."},"project_id":{"type":"string","format":"uuid","nullable":true,"description":"Only events of this project; null for every project."},"config_id":{"type":"string","format":"uuid","nullable":true,"description":"Only events of this config; null for every config."},"environment_id":{"type":"string","format":"uuid","nullable":true,"description":"Only events of this environment; null for every environment."}},"required":["id","scope_type","scope_id","url","description","event_types","enabled","status","disabled_at","disabled_reason","consecutive_failures","first_failure_at","signing_secret_hint","prev_signing_secret_active","prev_signing_secret_expires_at","legacy_signature","created_at","updated_at","project_id","config_id","environment_id"],"x-pc-sdk-model":"WebhookEndpoint"},"WebhookPaginationDto":{"type":"object","properties":{"next_cursor":{"type":"string","nullable":true,"description":"Pass as `cursor` to get the next page; null on the last page."},"has_more":{"type":"boolean","description":"Whether another page follows."}},"required":["next_cursor","has_more"],"x-pc-sdk-model":"WebhookPagination"},"ListWebhookEndpointsResponseDto":{"type":"object","properties":{"data":{"description":"The endpoints, newest first.","type":"array","items":{"$ref":"#/components/schemas/WebhookEndpointDto"}},"pagination":{"description":"Always one page (an endpoint limit applies).","allOf":[{"$ref":"#/components/schemas/WebhookPaginationDto"}]}},"x-pc-sdk-model":"WebhookEndpointList","x-pc-sdk-model-aliases":["ListWebhookEndpoints"],"required":["data","pagination"]},"CreateWebhookEndpointDto":{"type":"object","properties":{"url":{"type":"string","description":"Where to send events: an absolute https:// URL on a public host.","example":"https://api.acme.com/webhooks","maxLength":2048,"format":"uri"},"description":{"type":"string","nullable":true,"maxLength":200,"example":"Production receiver","description":"A label for people."},"event_types":{"type":"array","description":"Event types from `GET …/webhooks/event-types`. Empty or omitted means every event, including types added later.","example":["config.published","sdk_key.rotated"],"items":{"type":"string","enum":["config.published","sdk_key.rotated"]}},"enabled":{"type":"boolean","default":true,"example":true,"description":"Send `false` to create it switched off."},"project_id":{"type":"string","nullable":true,"format":"uuid","description":"Only events of this project. Omit or null for every project."},"config_id":{"type":"string","nullable":true,"format":"uuid","description":"Only events of this config (of `project_id`, when given)."},"environment_id":{"type":"string","nullable":true,"format":"uuid","description":"Only events of this environment, e.g. Production (of `project_id`, when given)."}},"required":["url"]},"WebhookEndpointWithSecretDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The endpoint's id."},"scope_type":{"type":"string","example":"workspace","description":"What owns the endpoint: `workspace`, `app` or `community`."},"scope_id":{"type":"string","description":"Id of the owning workspace, app or community."},"url":{"type":"string","format":"uri","example":"https://api.acme.com/webhooks","description":"Where events are sent."},"description":{"type":"string","nullable":true,"example":"Production receiver","description":"A label for people; null when unset."},"event_types":{"description":"Subscribed event types. Empty means every event, including types added later.","example":[],"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean","description":"The on/off switch (`PATCH … { enabled }`)."},"status":{"description":"`enabled` receives events. `disabled` was switched off. `auto_disabled` was switched off after 20 failed deliveries in a row or 24 hours of failures; `PATCH { enabled: true }` turns it back on.","allOf":[{"$ref":"#/components/schemas/WebhookEndpointStatus"}]},"disabled_at":{"type":"string","format":"date-time","nullable":true,"description":"When it was switched off; null while enabled."},"disabled_reason":{"nullable":true,"description":"`manual`: switched off by a caller. `failing`: switched off automatically after failed deliveries. Null while enabled.","allOf":[{"$ref":"#/components/schemas/WebhookEndpointDisabledReason"}]},"consecutive_failures":{"type":"number","description":"Failed automatic deliveries in a row; a success resets it."},"first_failure_at":{"type":"string","format":"date-time","nullable":true,"description":"Start of the current failure streak."},"signing_secret_hint":{"type":"string","description":"Last 4 characters of the signing secret.","example":"x9Q="},"prev_signing_secret_active":{"type":"boolean","description":"True while the previous secret still signs too (after a rotation, for its grace period)."},"prev_signing_secret_expires_at":{"type":"string","format":"date-time","nullable":true,"description":"Until then the previous secret signs too (after a rotation)."},"legacy_signature":{"type":"boolean","description":"True for endpoints carried over from the product's previous webhook system: they also receive the old signature header until its sunset date."},"created_at":{"type":"string","format":"date-time","description":"When the endpoint was created."},"updated_at":{"type":"string","format":"date-time","description":"When the endpoint last changed."},"project_id":{"type":"string","format":"uuid","nullable":true,"description":"Only events of this project; null for every project."},"config_id":{"type":"string","format":"uuid","nullable":true,"description":"Only events of this config; null for every config."},"environment_id":{"type":"string","format":"uuid","nullable":true,"description":"Only events of this environment; null for every environment."},"signing_secret":{"type":"string","description":"The signing secret, shown once: pass it unchanged to any Standard Webhooks verifier. Store it now; it cannot be shown again.","example":"whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"}},"required":["id","scope_type","scope_id","url","description","event_types","enabled","status","disabled_at","disabled_reason","consecutive_failures","first_failure_at","signing_secret_hint","prev_signing_secret_active","prev_signing_secret_expires_at","legacy_signature","created_at","updated_at","project_id","config_id","environment_id","signing_secret"],"x-pc-sdk-model":"WebhookEndpointWithSecret"},"UpdateWebhookEndpointDto":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri","example":"https://api.acme.com/webhooks","description":"A new absolute https:// URL on a public host."},"description":{"type":"string","nullable":true,"maxLength":200,"example":"Production receiver","description":"A new label; null clears it."},"event_types":{"type":"array","description":"Replaces the subscription. Event types from `GET …/webhooks/event-types`. Empty or omitted means every event, including types added later.","example":["config.published","sdk_key.rotated"],"items":{"type":"string","enum":["config.published","sdk_key.rotated"]}},"enabled":{"type":"boolean","description":"Switch it on or off. Switching on also clears an automatic disable.","example":true},"project_id":{"type":"string","nullable":true,"format":"uuid","description":"Project filter; null removes it."},"config_id":{"type":"string","nullable":true,"format":"uuid","description":"Config filter; null removes it."},"environment_id":{"type":"string","nullable":true,"format":"uuid","description":"Environment filter; null removes it."}}},"RotateWebhookSecretDto":{"type":"object","properties":{"grace_hours":{"type":"number","default":24,"minimum":0,"maximum":168,"description":"Hours the previous secret keeps signing too (0 ends it now).","example":24}}},"SendWebhookTestDto":{"type":"object","properties":{"event_type":{"type":"string","enum":["config.published","sdk_key.rotated"],"description":"Which event to send; its catalogue example is the `data`.","example":"config.published"}},"required":["event_type"]},"WebhookAttemptTrigger":{"type":"string","enum":["automatic","replay","test"]},"WebhookDeliveryAttemptDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The attempt's id."},"event_id":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$","example":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f","description":"The event that was delivered."},"endpoint_id":{"type":"string","format":"uuid","description":"The endpoint it was delivered to."},"event_type":{"type":"string","example":"user.created","description":"The event's type."},"attempt_number":{"type":"number","description":"1 for the first delivery; retries and replays count up."},"trigger":{"description":"`automatic` (first delivery or a retry), `replay` or `test`.","allOf":[{"$ref":"#/components/schemas/WebhookAttemptTrigger"}]},"url":{"type":"string","format":"uri","description":"Where it was sent."},"status_code":{"type":"number","nullable":true,"description":"HTTP status; null when no response came back."},"succeeded":{"type":"boolean","description":"True for a 2xx response."},"error_message":{"type":"string","nullable":true,"example":"request timed out","description":"Why the attempt failed when no 2xx came back; null on success."},"response_body":{"type":"string","nullable":true,"description":"The first 1 KiB of the response body."},"latency_ms":{"type":"number","nullable":true,"description":"Milliseconds until the response; null when none came back."},"attempted_at":{"type":"string","format":"date-time","description":"When the attempt was made."}},"required":["id","event_id","endpoint_id","event_type","attempt_number","trigger","url","status_code","succeeded","error_message","response_body","latency_ms","attempted_at"],"x-pc-sdk-model":"WebhookDeliveryAttempt"},"WebhookEventStatus":{"type":"string","enum":["pending","delivered","failed","not_sent"]},"WebhookEventDeliveryDto":{"type":"object","properties":{"endpoint_id":{"type":"string","format":"uuid","description":"The endpoint."},"attempt_number":{"type":"number","description":"Number of the latest attempt; retries and replays count up."},"status_code":{"type":"number","nullable":true,"description":"HTTP status of the latest attempt; null when no response came back."},"succeeded":{"type":"boolean","description":"True when the latest attempt got a 2xx."},"attempted_at":{"type":"string","format":"date-time","description":"When the latest attempt was made."},"next_attempt_at":{"type":"string","format":"date-time","nullable":true,"description":"When the next automatic attempt is due; null when none is queued."}},"required":["endpoint_id","attempt_number","status_code","succeeded","attempted_at","next_attempt_at"],"x-pc-sdk-model":"WebhookEventDelivery"},"WebhookEventDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$","example":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f","description":"Sent as `webhook-id`; the same on every retry and replay."},"type":{"example":"config.published","description":"The event type (one of this product's catalogue).","allOf":[{"$ref":"#/components/schemas/WebhookEventType"}]},"created_at":{"type":"string","format":"date-time","description":"When the event happened."},"test":{"type":"boolean","description":"Made by \"Send test\"."},"status":{"description":"`pending`: a delivery is queued. `failed`: the latest attempt to some endpoint failed and none is queued. `delivered`: every endpoint answered 2xx. `not_sent`: no endpoint subscribed.","allOf":[{"$ref":"#/components/schemas/WebhookEventStatus"}]},"payload":{"type":"object","additionalProperties":true,"description":"The JSON body exactly as sent."},"deliveries":{"description":"Latest attempt per endpoint (an endpoint whose first attempt is still queued is not listed yet).","type":"array","items":{"$ref":"#/components/schemas/WebhookEventDeliveryDto"}},"project_id":{"type":"string","format":"uuid","nullable":true,"description":"The project the event is about."},"config_id":{"type":"string","format":"uuid","nullable":true,"description":"The config the event is about."},"environment_id":{"type":"string","format":"uuid","nullable":true,"description":"The environment the event is about."}},"required":["id","type","created_at","test","status","payload","deliveries","project_id","config_id","environment_id"],"x-pc-sdk-model":"WebhookEvent"},"ListWebhookEventsResponseDto":{"type":"object","properties":{"data":{"description":"The events, newest first.","type":"array","items":{"$ref":"#/components/schemas/WebhookEventDto"}},"pagination":{"description":"The cursor for the next page.","allOf":[{"$ref":"#/components/schemas/WebhookPaginationDto"}]}},"x-pc-sdk-model":"WebhookEventList","x-pc-sdk-model-aliases":["ListWebhookEvents"],"required":["data","pagination"]},"WebhookEventDetailDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$","example":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f","description":"Sent as `webhook-id`; the same on every retry and replay."},"type":{"example":"config.published","description":"The event type (one of this product's catalogue).","allOf":[{"$ref":"#/components/schemas/WebhookEventType"}]},"created_at":{"type":"string","format":"date-time","description":"When the event happened."},"test":{"type":"boolean","description":"Made by \"Send test\"."},"status":{"description":"`pending`: a delivery is queued. `failed`: the latest attempt to some endpoint failed and none is queued. `delivered`: every endpoint answered 2xx. `not_sent`: no endpoint subscribed.","allOf":[{"$ref":"#/components/schemas/WebhookEventStatus"}]},"payload":{"type":"object","additionalProperties":true,"description":"The JSON body exactly as sent."},"deliveries":{"description":"Latest attempt per endpoint (an endpoint whose first attempt is still queued is not listed yet).","type":"array","items":{"$ref":"#/components/schemas/WebhookEventDeliveryDto"}},"project_id":{"type":"string","format":"uuid","nullable":true,"description":"The project the event is about."},"config_id":{"type":"string","format":"uuid","nullable":true,"description":"The config the event is about."},"environment_id":{"type":"string","format":"uuid","nullable":true,"description":"The environment the event is about."},"attempts":{"description":"Every attempt, newest first.","type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryAttemptDto"}}},"required":["id","type","created_at","test","status","payload","deliveries","project_id","config_id","environment_id","attempts"],"x-pc-sdk-model":"WebhookEventDetail"},"ReplayWebhookEventResponseDto":{"type":"object","properties":{"event_id":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$","description":"The replayed event (the same id as the original)."},"attempts":{"description":"One attempt per endpoint it was sent to.","type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryAttemptDto"}}},"x-pc-sdk-model":"WebhookEventReplay","x-pc-sdk-model-aliases":["ReplayWebhookEvent"],"required":["event_id","attempts"]},"FlagsHistoryUsageDto":{"type":"object","properties":{"project_id":{"type":"string","format":"uuid","description":"The project.","example":"3f9a1c52-7b1e-4d4a-9f0e-2a6c8b1d5e70"},"name":{"type":"string","description":"The project's name.","example":"Storefront"},"rows":{"type":"integer","description":"History rows the project keeps.","example":1240},"bytes":{"type":"integer","description":"Bytes of `before` / `after` the history rows hold.","example":524288},"max_rows":{"type":"integer","description":"Rows kept per project; the daily prune deletes the oldest beyond it.","example":50000},"max_bytes":{"type":"integer","description":"Bytes kept per project (200 MiB); the daily prune deletes the oldest beyond it.","example":209715200},"warning":{"type":"boolean","description":"True when the project uses 80% or more of either cap: the oldest history will soon be pruned. Export it first if you need it.","example":false}},"required":["project_id","name","rows","bytes","max_rows","max_bytes","warning"],"x-pc-sdk-model":"FlagsHistoryUsage"},"FlagsStatsResponseDto":{"type":"object","properties":{"projects":{"type":"integer","description":"Projects in the workspace.","example":1},"configs":{"type":"integer","description":"Configs across all projects.","example":2},"settings":{"type":"integer","description":"Feature flags and settings across all configs.","example":37},"segments":{"type":"integer","description":"Segments across all projects.","example":4},"changes_last_week":{"type":"integer","description":"Changes made by people and API keys in the last 7 days (system housekeeping such as snapshot pruning is not counted).","example":12},"last_change_at":{"type":"string","format":"date-time","nullable":true,"description":"When the latest change by a person or API key was made; null when there is none.","example":"2026-11-10T09:30:00.000Z"},"history_usage":{"description":"History usage per project against the retention caps.","type":"array","items":{"$ref":"#/components/schemas/FlagsHistoryUsageDto"}}},"required":["projects","configs","settings","segments","changes_last_week","last_change_at","history_usage"],"x-pc-sdk-model":"FlagsStats"},"FlagsImportSource":{"type":"string","enum":["configcat"]},"ConfigCatCredentialsDto":{"type":"object","properties":{"username":{"type":"string","writeOnly":true,"description":"Username of your ConfigCat Public Management API credentials (https://app.configcat.com/my-account/public-api-credentials). Used for this request only: never stored, logged or echoed.","example":"cc-basic-auth-username"},"password":{"type":"string","writeOnly":true,"format":"password","description":"Password of the same ConfigCat credentials. Used for this request only: never stored, logged or echoed.","example":"cc-basic-auth-password"}},"required":["username","password"]},"CreateImportDto":{"type":"object","properties":{"source":{"description":"Where to import from. Only `configcat` today.","example":"configcat","allOf":[{"$ref":"#/components/schemas/FlagsImportSource"}]},"credentials":{"writeOnly":true,"description":"ConfigCat Public Management API credentials (Basic auth). Write-only.","allOf":[{"$ref":"#/components/schemas/ConfigCatCredentialsDto"}]},"configcat_product_id":{"type":"string","format":"uuid","description":"Id of the ConfigCat product to import (Product settings in the ConfigCat dashboard, or `GET /v1/products`).","example":"08d8a0b0-0000-4c1f-8a1c-1a2b3c4d5e6f"},"dry_run":{"type":"boolean","description":"`true`: read and report only, write nothing (the first step). `false`: create the project.","example":true},"target_project_name":{"type":"string","minLength":1,"maxLength":100,"description":"Name of the new project. Defaults to the ConfigCat product's name; another project with this name is a 409.","example":"Checkout"},"skip_unsupported":{"type":"boolean","default":false,"description":"Import even when the dry run lists `unsupported` items: those rules (or segments, settings) are left out and named in the history. Without it, a real run with unsupported items answers 422 `IMPORT_UNSUPPORTED`."}},"required":["source","credentials","configcat_product_id","dry_run"]},"ImportCountsDto":{"type":"object","properties":{"environments":{"type":"number","description":"Environments the project gets.","example":2},"configs":{"type":"number","description":"Configs the project gets.","example":1},"settings":{"type":"number","description":"Feature flags and settings, over all configs.","example":12},"segments":{"type":"number","description":"Segments.","example":2},"rules":{"type":"number","description":"Targeting rules, over all settings and environments.","example":9}},"required":["environments","configs","settings","segments","rules"],"x-pc-sdk-model":"ImportCounts"},"FlagsImportMappedType":{"type":"string","enum":["environment","config","segment","setting"]},"ImportMappedItemDto":{"type":"object","properties":{"type":{"description":"What was mapped.","example":"setting","allOf":[{"$ref":"#/components/schemas/FlagsImportMappedType"}]},"source":{"type":"string","description":"ConfigCat's id of it (a uuid, or a number for settings).","example":"1234"},"key":{"type":"string","description":"The Flags key it gets.","example":"new_checkout"},"name":{"type":"string","description":"Its name.","example":"New checkout"},"config":{"type":"string","nullable":true,"description":"The Flags config key, for settings.","example":"main"}},"required":["type","source","key","name","config"],"x-pc-sdk-model":"ImportMappedItem"},"ImportUnsupportedItemDto":{"type":"object","properties":{"config":{"type":"string","nullable":true,"description":"The ConfigCat config name.","example":"Main"},"setting_key":{"type":"string","nullable":true,"description":"The setting key, when the item belongs to a setting.","example":"new_checkout"},"environment":{"type":"string","nullable":true,"description":"The ConfigCat environment name, when the item belongs to one environment.","example":"Production"},"segment":{"type":"string","nullable":true,"description":"The ConfigCat segment name, when the item is a segment.","example":null},"rule_index":{"type":"number","nullable":true,"description":"Zero-based index of the ConfigCat targeting rule, when the item is one rule.","example":1},"reason":{"type":"string","description":"Why it cannot be imported as it is, and what a real run with `skip_unsupported` does.","example":"The ConfigCat comparator \"regexMatches\" has no Flags equivalent."}},"required":["config","setting_key","environment","segment","rule_index","reason"],"x-pc-sdk-model":"ImportUnsupportedItem"},"ImportWarningDto":{"type":"object","properties":{"code":{"type":"string","description":"Stable code of the warning (open set): `predefined_variations`, `json_as_string`, `empty_split_attribute`, `protected_environment`, `catch_all_rule`, `unreachable_rules`, `missing_value`, `tags_dropped`.","example":"predefined_variations"},"message":{"type":"string","description":"What changes form in Flags.","example":"Flags has no predefined variations yet: these were imported as plain values."}},"required":["code","message"],"x-pc-sdk-model":"ImportWarning"},"ImportReportDto":{"type":"object","properties":{"counts":{"description":"What the project gets (after leaving out `unsupported`).","allOf":[{"$ref":"#/components/schemas/ImportCountsDto"}]},"mapped":{"description":"Every environment, config, segment and setting that maps, with the key it gets.","type":"array","items":{"$ref":"#/components/schemas/ImportMappedItemDto"}},"unsupported":{"description":"What cannot be imported as it is. A real run refuses while this is non-empty unless `skip_unsupported: true`.","type":"array","items":{"$ref":"#/components/schemas/ImportUnsupportedItemDto"}},"warnings":{"description":"What is imported in a different form.","type":"array","items":{"$ref":"#/components/schemas/ImportWarningDto"}}},"required":["counts","mapped","unsupported","warnings"],"x-pc-sdk-model":"ImportReport"},"ImportResponseDto":{"type":"object","properties":{"dry_run":{"type":"boolean","description":"Echo of the request: true when nothing was written.","example":true},"configcat_product_id":{"type":"string","description":"The ConfigCat product that was read.","format":"uuid","example":"08d8a0b0-0000-4c1f-8a1c-1a2b3c4d5e6f"},"report":{"description":"The mapping report (the same on the dry run and the real run).","allOf":[{"$ref":"#/components/schemas/ImportReportDto"}]},"project":{"nullable":true,"description":"The new project (real run); null on a dry run.","allOf":[{"$ref":"#/components/schemas/ProjectResponseDto"}]}},"required":["dry_run","configcat_product_id","report","project"],"x-pc-sdk-model":"Import"},"TargetingCondition":{"description":"One condition of a targeting rule: an object with exactly one of `user` (compare a user attribute), `segment` (in or not in a segment) or `prerequisite` (another flag's value for the same user).","oneOf":[{"$ref":"#/components/schemas/UserConditionDto"},{"$ref":"#/components/schemas/SegmentConditionDto"},{"$ref":"#/components/schemas/PrerequisiteConditionDto"}]},"TargetingRule":{"description":"A targeting rule: `conditions` (ANDed) and exactly one of `serve` (a value) or `percentages` (a split of the matching users).","oneOf":[{"$ref":"#/components/schemas/ServeRuleDto"},{"$ref":"#/components/schemas/SplitRuleDto"}]},"UserConditionValues":{"description":"A user condition's comparison values: an array of strings or numbers, or, for a confidential comparator in a response, the list's view `{hashed: true, count, list_id, editable}` (send it back unchanged to keep the list).","oneOf":[{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"number"}]},"description":"Cleartext comparison values."},{"$ref":"#/components/schemas/HashedValuesViewDto"}]},"ConfigPublishedEvent":{"type":"object","title":"ConfigPublishedEvent","description":"A change published a new revision of a config in one environment: SDKs download it on their next poll. One event per environment (a new flag publishes in every environment). Events can arrive out of order: order them by data.generation, then data.revision.","required":["id","type","created_at","data"],"properties":{"workspace_id":{"type":"string","format":"uuid","description":"The workspace the event belongs to, so you can route without opening `data`. Absent on \"Send test\" deliveries."},"id":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$","example":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f","description":"The event id, also sent as `webhook-id`; the same on every retry and replay."},"type":{"type":"string","enum":["config.published"],"description":"The event type. Switch on it to narrow the event."},"created_at":{"type":"string","format":"date-time","example":"2026-11-05T09:00:00.000Z","description":"When the event happened (the same on every retry)."},"test":{"type":"boolean","description":"Present and true only on a delivery made by \"Send test\"; its `data` is the catalogue example."},"data":{"$ref":"#/components/schemas/ConfigPublishedEventDataDto"}},"example":{"workspace_id":"9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b","id":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f","type":"config.published","created_at":"2026-11-05T09:00:00.000Z","data":{"project":{"id":"3c9d2f4e-1a2b-4c3d-8e9f-0a1b2c3d4e5f","name":"Storefront"},"config":{"id":"1f0c8b7a-6d5e-4f3a-9b2c-1d0e9f8a7b6c","key":"main","name":"Main"},"environment":{"id":"7a2e4c6d-8f0a-4b1c-9d3e-5f7a9b1c3d5e","key":"production","name":"Production"},"revision":13,"previous_revision":12,"generation":1,"etag":"q8w4Yb0cJ0dY2t1vUo3n7A","published_at":"2026-11-09T10:00:00.000Z","change":{"id":"0d1e2f3a-4b5c-4d6e-8f7a-9b0c1d2e3f4a","action":"setting_value.updated","note":"Ticket FLAG-142","actor":{"type":"user","id":"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9","label":"ada@example.com"}},"settings_changed":["new_checkout"]}},"x-pc-sdk-model":"ConfigPublishedEvent"},"SdkKeyRotatedEvent":{"type":"object","title":"SdkKeyRotatedEvent","description":"An environment's SDK key was rotated, or the previous key's grace period was ended early. Carries the key prefix only, never the key; reveal the new key in the console or through the API.","required":["id","type","created_at","data"],"properties":{"workspace_id":{"type":"string","format":"uuid","description":"The workspace the event belongs to, so you can route without opening `data`. Absent on \"Send test\" deliveries."},"id":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$","example":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f","description":"The event id, also sent as `webhook-id`; the same on every retry and replay."},"type":{"type":"string","enum":["sdk_key.rotated"],"description":"The event type. Switch on it to narrow the event."},"created_at":{"type":"string","format":"date-time","example":"2026-11-05T09:00:00.000Z","description":"When the event happened (the same on every retry)."},"test":{"type":"boolean","description":"Present and true only on a delivery made by \"Send test\"; its `data` is the catalogue example."},"data":{"$ref":"#/components/schemas/SdkKeyRotatedEventDataDto"}},"example":{"workspace_id":"9b2f6c1e-0d6a-4a63-9a43-2f1c3e4d5a6b","id":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f","type":"sdk_key.rotated","created_at":"2026-11-05T09:00:00.000Z","data":{"project":{"id":"3c9d2f4e-1a2b-4c3d-8e9f-0a1b2c3d4e5f","name":"Storefront"},"config":{"id":"1f0c8b7a-6d5e-4f3a-9b2c-1d0e9f8a7b6c","key":"main","name":"Main"},"environment":{"id":"7a2e4c6d-8f0a-4b1c-9d3e-5f7a9b1c3d5e","key":"production","name":"Production"},"reason":"rotated","slot":"primary","key_prefix":"pcf_sdk_8kQz","expires_at":"2026-11-10T10:00:00.000Z","change":{"id":"2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e","action":"sdk_key.rotated","note":null,"actor":{"type":"user","id":"5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9","label":"ada@example.com"}}}},"x-pc-sdk-model":"SdkKeyRotatedEvent"},"FlagsErrorCode":{"description":"Error codes this API returns (open set: a client must accept codes it does not know; new codes are not a breaking change). Each is documented at https://productcraft.co/docs/errors#<code>.","anyOf":[{"type":"string","enum":["BAD_REQUEST","VALIDATION_ERROR","UNAUTHORIZED","PAYMENT_REQUIRED","FORBIDDEN","NOT_FOUND","METHOD_NOT_ALLOWED","NOT_ACCEPTABLE","REQUEST_TIMEOUT","CONFLICT","GONE","PRECONDITION_FAILED","PAYLOAD_TOO_LARGE","UNSUPPORTED_MEDIA_TYPE","UNPROCESSABLE_ENTITY","PRECONDITION_REQUIRED","RATE_LIMITED","INTERNAL_SERVER_ERROR","NOT_IMPLEMENTED","BAD_GATEWAY","SERVICE_UNAVAILABLE","GATEWAY_TIMEOUT","SERVICE_NOT_ENABLED","INVALID_CREDENTIALS","SESSION_REVOKED","MCP_NOT_PERMITTED","MCP_WORKSPACE_MISMATCH","PAK_NOT_PERMITTED","ACTIONS_NOT_GRANTABLE","IDEMPOTENCY_KEY_REUSE","IDEMPOTENCY_KEY_REQUIRED","IDEMPOTENCY_IN_PROGRESS","WEBHOOK_ENDPOINT_LIMIT","WEBHOOK_ENDPOINT_NOT_FOUND","WEBHOOK_ENDPOINT_NOT_SUBSCRIBED","WEBHOOK_EVENT_NOT_FOUND","WEBHOOK_EVENT_TYPE_UNKNOWN","PROJECT_NOT_FOUND","ENVIRONMENT_NOT_FOUND","CONFIG_NOT_FOUND","SETTING_NOT_FOUND","SEGMENT_NOT_FOUND","CHANGE_NOT_FOUND","REVISION_NOT_FOUND","SDK_KEY_NOT_FOUND","KEY_ALREADY_EXISTS","LAST_ENVIRONMENT","VERSION_CONFLICT","SETTING_IN_USE","SEGMENT_IN_USE","CIRCULAR_PREREQUISITE","PREREQUISITE_NOT_FOUND","PREREQUISITE_TYPE_MISMATCH","INVALID_VALUE","INVALID_TARGETING","PERCENTAGES_MUST_SUM_TO_100","CONFIG_TOO_LARGE","LIMIT_EXCEEDED","CONFIRMATION_REQUIRED","NOTE_REQUIRED","CONFIDENTIAL_LIST_NOT_EDITABLE","REVERT_NOT_SUPPORTED","NOTHING_TO_RESTORE","EVALUATION_BUDGET_EXCEEDED","MANAGEMENT_UNAVAILABLE","IMPORT_CREDENTIALS_INVALID","IMPORT_SOURCE_UNAVAILABLE","IMPORT_SOURCE_NOT_FOUND","IMPORT_UNSUPPORTED","IMPORT_EXCEEDS_LIMITS","OWNER_NOT_A_MEMBER","SETTING_TYPE_IMMUTABLE"]},{"type":"string","description":"A code added after this document was published."}],"x-pc-open-enum":true,"x-pc-error-docs":"https://productcraft.co/docs/errors#{code}","x-enum-descriptions":{"BAD_REQUEST":"The request is malformed (not valid JSON, a bad header, an unusable parameter).","VALIDATION_ERROR":"One or more request fields are invalid; `errors` lists each field (`param`, `message`, `code`).","UNAUTHORIZED":"No credentials, or the token or API key is invalid, expired or revoked.","PAYMENT_REQUIRED":"The workspace has no credit or plan for this operation.","FORBIDDEN":"The caller is authenticated but not allowed to do this.","NOT_FOUND":"The resource does not exist, or belongs to another workspace or app.","METHOD_NOT_ALLOWED":"The route does not accept this HTTP method.","NOT_ACCEPTABLE":"The route cannot produce the requested content type.","REQUEST_TIMEOUT":"The request took too long to arrive.","CONFLICT":"The request conflicts with the current state of the resource.","GONE":"The resource existed but has been removed for good.","PRECONDITION_FAILED":"A precondition header did not match.","PAYLOAD_TOO_LARGE":"The request body is over the size limit.","UNSUPPORTED_MEDIA_TYPE":"The request body is not in a content type the route accepts.","UNPROCESSABLE_ENTITY":"The request is well-formed but cannot be carried out.","PRECONDITION_REQUIRED":"The route requires a precondition header.","RATE_LIMITED":"Too many requests; retry after the `Retry-After` header.","INTERNAL_SERVER_ERROR":"An unexpected server error. Retrying is safe for idempotent requests; quote `request_id` to support.","NOT_IMPLEMENTED":"The server does not support this operation.","BAD_GATEWAY":"An upstream service returned an invalid response.","SERVICE_UNAVAILABLE":"The service or one of its dependencies is temporarily unavailable; retry.","GATEWAY_TIMEOUT":"An upstream service did not answer in time; retry.","SERVICE_NOT_ENABLED":"The workspace has not enabled this product.","INVALID_CREDENTIALS":"The credentials were not accepted.","SESSION_REVOKED":"The session behind this token was signed out or revoked.","MCP_NOT_PERMITTED":"An MCP (agent) token cannot call this route.","MCP_WORKSPACE_MISMATCH":"The MCP token was issued for a different workspace.","PAK_NOT_PERMITTED":"A workspace API key cannot call this route.","ACTIONS_NOT_GRANTABLE":"The policy grants actions the caller does not hold.","IDEMPOTENCY_KEY_REUSE":"The `Idempotency-Key` was already used with a different body or route.","IDEMPOTENCY_KEY_REQUIRED":"This operation requires an `Idempotency-Key` header.","IDEMPOTENCY_IN_PROGRESS":"A request with the same `Idempotency-Key` is still running. Retry after `Retry-After` seconds with the same key to get its response.","WEBHOOK_ENDPOINT_LIMIT":"The workspace has the maximum number of webhook endpoints.","WEBHOOK_ENDPOINT_NOT_FOUND":"No webhook endpoint with this id in this workspace.","WEBHOOK_ENDPOINT_NOT_SUBSCRIBED":"The endpoint is not subscribed to this event type.","WEBHOOK_EVENT_NOT_FOUND":"No webhook event with this id in this workspace.","WEBHOOK_EVENT_TYPE_UNKNOWN":"The event type is not one this product sends.","PROJECT_NOT_FOUND":"The project does not exist in this workspace.","ENVIRONMENT_NOT_FOUND":"The environment does not exist in this project.","CONFIG_NOT_FOUND":"The config does not exist in this workspace.","SETTING_NOT_FOUND":"The feature flag or setting does not exist in this workspace.","SEGMENT_NOT_FOUND":"The segment does not exist in this workspace.","CHANGE_NOT_FOUND":"The change does not exist in this workspace.","REVISION_NOT_FOUND":"The config revision does not exist for this environment.","SDK_KEY_NOT_FOUND":"The SDK key is unknown, revoked or expired.","KEY_ALREADY_EXISTS":"Another resource in the same scope already uses this key.","LAST_ENVIRONMENT":"A project needs at least one environment; this is the last one.","VERSION_CONFLICT":"The resource changed since you read it; reload and apply your change again.","SETTING_IN_USE":"Another setting uses this one as a prerequisite.","SEGMENT_IN_USE":"A targeting rule uses this segment.","CIRCULAR_PREREQUISITE":"The prerequisite would create a cycle between settings.","PREREQUISITE_NOT_FOUND":"The prerequisite setting does not exist in this config.","PREREQUISITE_TYPE_MISMATCH":"The comparison value does not match the prerequisite setting's type.","INVALID_VALUE":"The value does not match the setting's type or exceeds its size limit.","INVALID_TARGETING":"The targeting rules are not valid.","PERCENTAGES_MUST_SUM_TO_100":"The percentage options must add up to 100.","CONFIG_TOO_LARGE":"The rendered config would exceed the maximum config size.","LIMIT_EXCEEDED":"The workspace has reached a Flags limit.","CONFIRMATION_REQUIRED":"The request needs an explicit confirmation parameter.","NOTE_REQUIRED":"This environment requires a change note.","CONFIDENTIAL_LIST_NOT_EDITABLE":"The confidential list was sent pre-hashed, so it has no cleartext to edit, re-hash or reveal; send the full list instead.","REVERT_NOT_SUPPORTED":"This kind of change cannot be restored.","NOTHING_TO_RESTORE":"The entity already matches the version before this change.","EVALUATION_BUDGET_EXCEEDED":"The test evaluation ran over its time budget.","MANAGEMENT_UNAVAILABLE":"The management API is temporarily unavailable; SDK config delivery keeps serving.","IMPORT_CREDENTIALS_INVALID":"ConfigCat rejected the import credentials.","IMPORT_SOURCE_UNAVAILABLE":"The ConfigCat API could not be reached.","IMPORT_SOURCE_NOT_FOUND":"The ConfigCat product does not exist or the credentials cannot see it.","IMPORT_UNSUPPORTED":"The ConfigCat product uses features Flags cannot import; see details.items.","IMPORT_EXCEEDS_LIMITS":"The ConfigCat product is larger than the Flags workspace limits.","OWNER_NOT_A_MEMBER":"The owner_id is not a member of this workspace, or membership could not be checked with this credential.","SETTING_TYPE_IMMUTABLE":"A setting's type cannot change; create a new setting instead."}}},"headers":{"X-RateLimit-Limit-short":{"description":"Requests allowed per second from this client IP (20).","schema":{"type":"integer"}},"X-RateLimit-Remaining-short":{"description":"Requests left in the current one-second window.","schema":{"type":"integer"}},"X-RateLimit-Reset-short":{"description":"Seconds until the one-second window resets.","schema":{"type":"integer"}},"X-RateLimit-Limit-long":{"description":"Requests allowed per minute from this client IP (600).","schema":{"type":"integer"}},"X-RateLimit-Remaining-long":{"description":"Requests left in the current one-minute window.","schema":{"type":"integer"}},"X-RateLimit-Reset-long":{"description":"Seconds until the one-minute window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying. Sent on every 429.","schema":{"type":"integer"}},"Retry-After-short":{"description":"Deprecated: read `Retry-After`. Seconds to wait, when the per-second IP limit tripped.","deprecated":true,"schema":{"type":"integer"}},"Retry-After-long":{"description":"Deprecated: read `Retry-After`. Seconds to wait, when the per-minute IP limit tripped.","deprecated":true,"schema":{"type":"integer"}},"RequestId":{"description":"The request's id: the inbound `X-Request-Id` when it is 1 to 128 characters of `A-Z a-z 0-9 . _ : -`, otherwise a fresh `req_...` id. Error bodies repeat it as `request_id`. Quote it when contacting support.","schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$","example":"req_6f1c2a9d4b7e4f0a8c3d2e1f0a9b8c7d"}}}},"x-webhooks":{"config.published":{"post":{"summary":"A change published a new revision of a config in one environment: SDKs download it on their next poll. One event per environment (a new flag publishes in every environment). Events can arrive out of order: order them by data.generation, then data.revision.","description":"A `config.published` event (Configs), POSTed as JSON to every enabled endpoint subscribed to it and signed with the Standard Webhooks headers. Answer with any 2xx within 15 s to acknowledge it; anything else, or no answer, is retried after 1 min, 5 min, 30 min, 2 h, 6 h, 24 h.","tags":["webhooks"],"x-pc-webhook-category":"Configs","parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event id: the same on every retry and replay, so dedupe on it. Part of the signed content.","schema":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$"},"example":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds of this attempt. Part of the signed content; reject a delivery more than 5 minutes from your clock.","schema":{"type":"string","pattern":"^\\d+$"},"example":"1793869200"},{"name":"webhook-signature","in":"header","required":true,"description":"`v1,<base64 HMAC-SHA256 of \"<webhook-id>.<webhook-timestamp>.<raw body>\">`, keyed with the base64-decoded part of the endpoint's `whsec_` secret. During a secret rotation it carries one space-separated `v1,` entry per active secret; accept the delivery when any entry matches.","schema":{"type":"string"},"example":"v1,lkO4DTG3zOoxV5QD2PC5B41Sc8nqZNoh50NPrwnhJ5I="}],"requestBody":{"required":true,"description":"The `config.published` event. Verify the signature over the raw body before parsing it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigPublishedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the event. Answer with any 2xx within 15 s to acknowledge it; anything else, or no answer, is retried after 1 min, 5 min, 30 min, 2 h, 6 h, 24 h."}}}},"sdk_key.rotated":{"post":{"summary":"An environment's SDK key was rotated, or the previous key's grace period was ended early. Carries the key prefix only, never the key; reveal the new key in the console or through the API.","description":"A `sdk_key.rotated` event (SDK keys), POSTed as JSON to every enabled endpoint subscribed to it and signed with the Standard Webhooks headers. Answer with any 2xx within 15 s to acknowledge it; anything else, or no answer, is retried after 1 min, 5 min, 30 min, 2 h, 6 h, 24 h.","tags":["webhooks"],"x-pc-webhook-category":"SDK keys","parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The event id: the same on every retry and replay, so dedupe on it. Part of the signed content.","schema":{"type":"string","pattern":"^evt_[0-9a-f-]{36}$"},"example":"evt_3f0c3c1e-8a2b-4c55-9d3f-0a1b2c3d4e5f"},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds of this attempt. Part of the signed content; reject a delivery more than 5 minutes from your clock.","schema":{"type":"string","pattern":"^\\d+$"},"example":"1793869200"},{"name":"webhook-signature","in":"header","required":true,"description":"`v1,<base64 HMAC-SHA256 of \"<webhook-id>.<webhook-timestamp>.<raw body>\">`, keyed with the base64-decoded part of the endpoint's `whsec_` secret. During a secret rotation it carries one space-separated `v1,` entry per active secret; accept the delivery when any entry matches.","schema":{"type":"string"},"example":"v1,lkO4DTG3zOoxV5QD2PC5B41Sc8nqZNoh50NPrwnhJ5I="}],"requestBody":{"required":true,"description":"The `sdk_key.rotated` event. Verify the signature over the raw body before parsing it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SdkKeyRotatedEvent"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the event. Answer with any 2xx within 15 s to acknowledge it; anything else, or no answer, is retried after 1 min, 5 min, 30 min, 2 h, 6 h, 24 h."}}}}},"x-pc-webhook-signing":{"scheme":"standard-webhooks","spec_url":"https://www.standardwebhooks.com","algorithm":"HMAC-SHA256","headers":{"id":"webhook-id","timestamp":"webhook-timestamp","signature":"webhook-signature"},"signed_content":"{webhook-id}.{webhook-timestamp}.{body}","signature_format":"v1,<base64>","secret_prefix":"whsec_","secret_key":"base64 decode of the part after `whsec_`; a secret without the prefix (minted before it) is used as its UTF-8 bytes","tolerance_seconds":300,"rotation":"space-separated `v1,` entries, one per active secret, current first"}}