Skip to content

Public State ​

Public state is versioned JSON state scoped by account, project, and environment. It is readable anonymously through the readonly route and readable or writable by developer bearer tokens or project API keys.

See what public state is for and what not to store.

Most developers should use the SDK, CLI, or console instead of calling these endpoints directly.

Developer Or API-Key Routes ​

text
GET   /v1/{accountId}/projects/{slug}/public-state/{env}
PUT   /v1/{accountId}/projects/{slug}/public-state/{env}
PATCH /v1/{accountId}/projects/{slug}/public-state/{env}
GET   /v1/{accountId}/projects/{slug}/public-state/{env}/versions

These routes accept Authorization: Bearer <developer-token> or Authorization: ApiKey <sky_...>. A valid API key that belongs to a different project in the same account returns 403 with no body; an unknown account or project returns 404.

Anonymous Readonly Route ​

text
GET /v1/readonly/{accountId}/projects/{slug}/public-state/{env}

This route is used by SDK public-state reads. It sets ETag and Cache-Control; development and staging responses use a short cache window, while production responses use a longer one.

Write Semantics ​

  • Public state must be a JSON object.
  • Creates use If-None-Match: *. When If-None-Match: * is the only precondition header, the write succeeds only when no state exists yet; if state already exists it returns 412. On PATCH, the operations apply to an empty {} document.
  • Updates use a quoted positive version, If-Match: "N". A stale or missing version returns 412, and If-Match: "0" always returns 412.
  • Sending both headers never succeeds. The server evaluates If-Match first, following RFC 9110, and the create-only If-None-Match: * guard then fails against the same state, so If-Match: "N" together with If-None-Match: * always returns 412 (whether or not version N exists). If-Match together with any If-None-Match value other than exactly * returns 400 validation_error.
  • A write with neither header returns 400 validation_error.
  • Successful writes return 200 with version, state, comment, createdAt, and stateSizeBytes.
  • Every accepted PATCH creates a new version and returns 200, even when the operations leave the data unchanged; the comment is still recorded on that version. The same rule applies to user state.
  • PATCH expects an ops array of JSON Patch operations and optional comment. See Patch rejection codes for the failure semantics.
  • Public state and user state must not exceed 256,000 characters when serialized as JSON (UTF-16 code units, which is what JSON.stringify(state).length returns). This limit is the same on every tier. An oversize PUT returns 400 validation_error; an oversize PATCH returns 400 patch_state_too_large (see Patch rejection codes).