User State
User state is versioned JSON state scoped by account, project, environment, and the signed-in end user. Each end-user bearer token can read and write only its own state.
Use it for per-user preferences, saved settings, progress, and other data that belongs to one signed-in user. Do not use it for secrets or for data that must be shared across users.
Most developers should use the SDK instead of calling these endpoints directly.
End-User Routes
text
GET /v1/{accountId}/projects/{slug}/user-state/{env}
PATCH /v1/{accountId}/projects/{slug}/user-state/{env}These routes accept Authorization: Bearer <end-user-token>.
A GET returns 200 with { version, state } and an ETag header when state exists, and 204 with no body when the user has no state yet.
Write Semantics
- User state must be a JSON object.
- Creates use
If-None-Match: *. The write succeeds only when no state exists yet; if state already exists it returns412. OnPATCH, the operations apply to an empty{}document. - Updates use a quoted positive version,
If-Match: "N". A stale or missing version returns412, andIf-Match: "0"always returns412. - When both headers are sent, the server evaluates
If-Matchfirst, following RFC 9110.If-Match: "N"together withIf-None-Match: *is an update-then-create write: it updates versionNif that version exists, and otherwise creates the state.If-Matchtogether with anyIf-None-Matchvalue other than exactly*returns400with{ error: "validation_error", message: "If-None-Match must contain only *" }. - A write with neither header returns
400with{ error: "validation_error", message: "If-Match or If-None-Match header is required" }. - Successful writes return
200withversionandstateonly; unlike public state, the response carries nocommentorstateSizeBytes. - Every accepted
PATCHcreates a new version and returns200, even when the operations leave the data unchanged. PATCHexpects anopsarray of JSON Patch operations and uses the same operation set as public-statePATCH.