/projects/{slug}/environments/{environmentSlug}/variables/{name}Partial update of one variable, addressed by its current name and matched without regard to case. Every field is optional and omitted fields keep their current value.
value is ciphertext. If present it must start with v1: or v2:, otherwise 400 variable.ciphertext_invalid with error.field: "value". The server cannot encrypt for you, so encrypt with the workspace key before sending.
defaultValue is ciphertext too, same workspace key, same prefix, validated the same way when it is a string. Send null to clear it. Omit it to leave it alone. A plaintext defaultValue that slips through another path is permanent plaintext and is copied into every version snapshot taken afterwards.
Passing name renames the variable, which changes the URL you address it by. The new name must match ^[A-Za-z_][A-Za-z0-9_]*$ and be 1 to 100 characters, and the rename is rejected if another live variable already holds that name, compared without regard to case.
Requires the variables:write scope.
curl --request PATCH \
--url 'https://api.envless.cloud/projects/<slug>/environments/<environmentSlug>/variables/<name>' \
--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>"
}'https://api.envless.cloud/projects/{slug}/environments/{environmentSlug}/variables/{name}Response headers
Authorization
AuthorizationstringrequiredheaderBearer token: an Envless API key (
ev_sk_…), created in the dashboard or withPOST /keys. The key is bound to one workspace; every request runs inside it.
Path parameters
slugstringrequiredProject slug or project uniqueId.
environmentSlugstringrequiredEnvironment slug.
namestringrequiredCurrent variable name, matched without regard to case. URL-encode it only for a legacy name holding characters outside
[A-Za-z0-9_].
Query parameters
productstringProduct slug, to disambiguate a project slug shared across products.
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, and is stored with the casing you send. Renaming changes the URL of this variable.valuestringmin length 1max length 20000pattern ^v[12]:CIPHERTEXT. Must start with
v1:orv2:.typeenum<string>Options:
"string","number","boolean"isSecretbooleanvisibilityenum<string>Options:
"server","client"requiredbooleandefaultValuestring | nullmax length 20000pattern ^v[12]:CIPHERTEXT, same key and prefix as
value.nullclears it, omitting keeps it.
Responses
200OK
Update a variable by name succeeded.
successbooleanrequiredcodeintegerrequiredThe HTTP status of this response, repeated in the body.
messagestringrequirederrornullrequireddataobjectrequiredShow child attributesHide child attributes
idstringrequirednamestringrequiredReturned with the casing it was stored with. Live variables in one environment are unique without regard to case.
valuestring | nullCiphertext. Decrypt client-side with the workspace key.
typeenum<string>requiredOptions:
"string","number","boolean"visibilityenum<string>requiredOptions:
"server","client"requiredbooleanrequireddefaultValuestring | nullCiphertext, encrypted with the same workspace key as
value.environmentIdstringrequiredcreatedAtstringrequireddate-timeupdatedAtstring | nulldate-time
_reqobjectShow child attributesHide child attributes
reqIdstringresTimeinteger | 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.
successbooleanrequiredcodeintegerrequiredThe HTTP status of this response, repeated in the body.
messagestringrequirederrorobjectrequiredMachine-readable failure detail. Null on success.
Show child attributesHide child attributes
codeenum<string>requiredStable 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"resourcestringThe resource or scope the failure relates to.
fieldstringThe request field that caused the failure.
dataobject | nullrequiredNull on most failures. A plan limit carries
{ limit, current }._reqobjectShow child attributesHide child attributes
reqIdstringresTimeinteger | 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-valueordefaultValueis notv1:/v2:ciphertext;error.fieldnames it.request.invalid- the service refused the new name, type, visibility, required flag or value;messagesays why.
401Unauthorized
auth.api_key_required- theAuthorizationheader is missing, or its value does not start withev_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 project is locked by the plan's project limit.
403Forbidden
auth.key_project_restricted- the key's project allowlist excludes this project, orauth.product_restrictedfor 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.resourcenames it.
404Not Found
project.not_found- no project with that slug in the workspace.request.not_found- the environment does not exist, or it holds no live variable of that name.
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.