Variables

Update a variable by id

Id-addressed twin of PATCH /projects/{slug}/environments/{environmentSlug}/variables/{name}, with identical body and semantics.

PATCH/variables/{id}

Id-addressed twin of PATCH /projects/{slug}/environments/{environmentSlug}/variables/{name}, with identical body and semantics. Prefer this one in sync clients that already track ids, since it survives renames and needs no project or environment lookup.

value is ciphertext and must start with v1: or v2:, otherwise 400 variable.ciphertext_invalid with error.field: "value". defaultValue is ciphertext too, same workspace key and same prefix, null clears it and omitting leaves it alone. The server holds no key and cannot encrypt on your behalf.

Note the ordering quirk: the variable is looked up before the ciphertext is validated on this route, the reverse of the name-addressed route, so a bad ciphertext against an unknown id returns 404 rather than 400.

Requires the variables:write scope.

curl --request PATCH \
  --url 'https://api.envless.cloud/variables/<id>' \
  --header 'Authorization: Bearer ev_sk_xxxxxxxxxxxx' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "STRIPE_SECRET_KEY",
  "value": "v1:8Wm3kQ...ciphertext",
  "type": "string",
  "isSecret": true,
  "visibility": "server",
  "required": false,
  "defaultValue": "<string>"
}'
Try itPATCHhttps://api.envless.cloud/variables/{id}
Path parameters

Authorization

  • Authorizationstringrequiredheader

    Bearer token: an Envless API key (ev_sk_…), created in the dashboard or with POST /keys. The key is bound to one workspace; every request runs inside it.

Path parameters

  • idstringrequireduuid

    Variable uniqueId (uuid v7).

Request body

application/json · required

  • namestringmin length 1max length 100pattern ^[A-Za-z_][A-Za-z0-9_]*$

    New name. Must match ^[A-Za-z_][A-Za-z0-9_]*$ and be 1 to 100 characters, is stored with the casing you send, and is rejected when another live variable in the same environment already holds it, compared without regard to case.

  • valuestringmin length 1max length 20000pattern ^v[12]:

    CIPHERTEXT. Must start with v1: or v2:.

  • typeenum<string>

    Options: "string", "number", "boolean"

  • isSecretboolean
  • visibilityenum<string>

    Options: "server", "client"

  • requiredboolean
  • defaultValuestring | nullmax length 20000pattern ^v[12]:

    CIPHERTEXT, same key and prefix as value. null clears it.

Responses

200OK

Update a variable by id succeeded.

  • successbooleanrequired
  • codeintegerrequired

    The HTTP status of this response, repeated in the body.

  • messagestringrequired
  • errornullrequired
  • dataobjectrequired
    Show child attributesHide child attributes
    • idstringrequired
    • namestringrequired

      Returned with the casing it was stored with. Live variables in one environment are unique without regard to case.

    • valuestring | null

      Ciphertext. Decrypt client-side with the workspace key.

    • typeenum<string>required

      Options: "string", "number", "boolean"

    • visibilityenum<string>required

      Options: "server", "client"

    • requiredbooleanrequired
    • defaultValuestring | null

      Ciphertext, encrypted with the same workspace key as value.

    • environmentIdstringrequired
    • createdAtstringrequireddate-time
    • updatedAtstring | nulldate-time
  • _reqobject
    Show child attributesHide child attributes
    • reqIdstring
    • resTimeinteger | null
{
    "success": true,
    "code": 200,
    "message": "OK",
    "error": null,
    "data": {
        "id": "<string>",
        "name": "<string>",
        "value": "<string>",
        "type": "string",
        "visibility": "server",
        "required": true,
        "defaultValue": "<string>",
        "environmentId": "<string>",
        "createdAt": "2026-05-30T10:14:22.000Z",
        "updatedAt": "2026-05-30T10:14:22.000Z"
    },
    "_req": {
        "reqId": "<string>",
        "resTime": 1
    }
}

Error envelope

Every failure below returns the same shape with success: false; branch on error.code, never on message.

  • successbooleanrequired
  • codeintegerrequired

    The HTTP status of this response, repeated in the body.

  • messagestringrequired
  • errorobjectrequired

    Machine-readable failure detail. Null on success.

    Show child attributesHide child attributes
    • codeenum<string>required

      Stable error code. Branch on this, never on message.

      Options: "auth.api_key_required", "auth.api_key_not_found", "auth.api_key_user_missing", "auth.api_key_owner_not_member", "auth.scope_missing", "auth.scope_ceiling_exceeded", "auth.key_project_restricted", "auth.product_restricted", "auth.permission_denied", "auth.self_mutation_forbidden", "auth.step_up_required", "auth.step_up_fresh_required", "auth.cli_token_not_accepted", "auth.two_factor_required", "auth.workspace_two_factor_required", "auth.two_factor_invalid", "auth.two_factor_replayed", "auth.two_factor_locked", "auth.two_factor_not_enabled", "auth.two_factor_already_enabled", "request.body_must_be_json", "request.body_invalid", "request.body_too_large", "request.rate_limited", "request.invalid_pagination", "workspace.not_found", "workspace.slug_conflict", "workspace.limit_reached", "workspace.delete_last", "workspace.delete_too_early", "workspace.delete_has_projects", "domain.not_configured", "domain.not_found", "domain.invalid", "domain.taken", "domain.attempt_limit", "product.not_found", "product.slug_conflict", "product.locked", "project.not_found", "project.ambiguous_product", "project.slug_conflict", "environment.not_found", "environment.slug_conflict", "environment.expose_disabled", "environment.expose_private_product", "variable.not_found", "variable.name_conflict", "variable.ciphertext_invalid", "variable.baseline_drifted", "version.not_found", "member.not_found", "member.already_exists", "member.self_invite", "member.self_mutation", "member.owner_immutable", "member.owner_cannot_leave", "member.seat_limit", "invite.already_pending", "role.owner_not_assignable", "role.limit_reached", "role.immutable", "role.in_use", "invite.not_found", "invite.expired", "role.not_found", "role.name_conflict", "key.not_found", "key.limit_reached", "webhook.not_found", "webhook.delivery_not_found", "plan.limit_reached", "plan.upgrade_required", "request.not_found", "request.method_not_allowed", "request.conflict", "auth.unauthorized", "auth.forbidden", "request.invalid", "server.error"

    • resourcestring

      The resource or scope the failure relates to.

    • fieldstring

      The request field that caused the failure.

  • dataobject | nullrequired

    Null on most failures. A plan limit carries { limit, current }.

  • _reqobject
    Show child attributesHide child attributes
    • reqIdstring
    • resTimeinteger | null
{
    "success": false,
    "code": 400,
    "message": "Something went wrong.",
    "error": {
        "code": "auth.api_key_required",
        "resource": "<string>",
        "field": "<string>"
    },
    "data": {},
    "_req": {
        "reqId": "<string>",
        "resTime": 1
    }
}

400Bad Request

  • request.body_must_be_json - the body is absent or not valid JSON.
  • variable.ciphertext_invalid - value or defaultValue is not v1:/v2: ciphertext; error.field names it.
  • request.invalid - the service refused the new name, type, visibility, required flag or value; message says why.

401Unauthorized

  • auth.api_key_required - the Authorization header is missing, or its value does not start with ev_sk_.
  • auth.api_key_not_found - the key is unknown, inactive or revoked.
  • auth.api_key_user_missing - the key is valid but its owner no longer exists.
  • auth.api_key_owner_not_member - the key's owner is no longer a member of the key's workspace.

402Payment Required

plan.upgrade_required - the variable's project is locked by the plan's project limit.

403Forbidden

  • auth.key_project_restricted - the key's project allowlist excludes the variable's project, or auth.product_restricted for an inaccessible private product.
  • auth.workspace_two_factor_required - the workspace requires two-factor authentication and the key's owner has not turned it on.
  • auth.scope_missing - the key lacks a scope this operation requires; error.resource names it.

404Not Found

request.not_found - no live variable with that id in this workspace.

409Conflict

variable.name_conflict - a rename collides with another live variable in the same environment, compared without regard to case.

413Payload Too Large

request.body_too_large - the request body is larger than 1 MiB (1,048,576 bytes).

500Internal Server Error

server.error - an unexpected error; retry with backoff.

503Service Unavailable

server.error - the API is in maintenance mode or is missing its configuration; retry with backoff.