Versions

Roll back to a version

Restores an environment to a snapshot, in one transaction behind the same per-environment advisory lock that variables/apply uses.

POST/versions/{id}/rollback

Restores an environment to a snapshot, in one transaction behind the same per-environment advisory lock that variables/apply uses. The environment is derived from the version, there is no environment in the path.

What it does, by name: variables present in the snapshot but missing live are re-created, variables present in both are overwritten when anything differs (value, type, isSecret, visibility, required, defaultValue), and live variables absent from the snapshot are soft-deleted. Ids are not preserved, a re-created variable gets a new id, so any client caching ids must re-read afterwards.

Rollback does not snapshot the current state first. Call POST .../versions before rolling back if you might want to come back.

The restored ciphertext is whatever was stored in the snapshot, copied verbatim. If the workspace passphrase was rotated without also re-encrypting the version entries, this call succeeds and writes values that no longer decrypt under the current key. Nothing warns you. Rotate version entries whenever you rotate live variables.

Requires both versions:write and variables:write.

Plan gate. Rollback needs a paid plan. On Free every rollback, including one to the latest version, returns 402 plan.upgrade_required with error.resource: "version" and nothing is restored. Dev, Team and Enterprise can roll back to any version.

Requires the versions:write or variables:write scope.

curl --request POST \
  --url 'https://api.envless.cloud/versions/<id>/rollback' \
  --header 'Authorization: Bearer ev_sk_xxxxxxxxxxxx'
Try itPOSThttps://api.envless.cloud/versions/{id}/rollback
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

    Version uniqueId (uuid v7) to restore. Must belong to the workspace behind the key.

Responses

200OK

Roll back to a version succeeded.

  • successbooleanrequired
  • codeintegerrequired

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

  • messagestringrequired
  • errornullrequired
  • dataobjectrequired
    Show child attributesHide child attributes
    • versionLabelstringrequired

      Label of the version that was restored, for example v3.

    • addedintegerrequired

      Variables re-created because they were in the snapshot but not live. New ids.

    • updatedintegerrequired

      Live variables overwritten because at least one field differed.

    • removedintegerrequired

      Live variables soft-deleted because the snapshot did not contain them.

  • _reqobject
    Show child attributesHide child attributes
    • reqIdstring
    • resTimeinteger | null
{
    "success": true,
    "code": 200,
    "message": "OK",
    "error": null,
    "data": {
        "versionLabel": "<string>",
        "added": 1,
        "updated": 1,
        "removed": 1
    },
    "_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_invalid - the version holds variable names that are no longer valid; rename them before rolling back.

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 version's project is locked by the plan's project limit, or the workspace is on the Free plan, where rollback is unavailable for every version including the latest. In the plan case error.resource is version and nothing is restored.

403Forbidden

  • auth.scope_missing - the key lacks versions:write or variables:write, both are required. Also auth.key_project_restricted and auth.product_restricted when the key or its owner cannot reach the version's project or product.
  • auth.workspace_two_factor_required - the workspace requires two-factor authentication and the key's owner has not turned it on.

404Not Found

request.not_found - no version with that id in this workspace, or the version disappeared between the lookup and the transaction.

409Conflict

variable.name_conflict - a restored name already exists in the environment, differing only by letter case.

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.

Rollback needs the Dev plan or above. On Free the workspace keeps only the latest published version, and this route answers 402 with error.code plan.upgrade_required, error.resource version and Rollback needs a paid plan. Upgrade to restore an earlier version. Nothing is deleted on a downgrade, so the same id restores again once the plan is back. See Plans and billing.