---
title: "Restore an archived environment"
method: POST
path: "/projects/{projectId}/environments/{environmentId}/restore"
tags: ["Environments"]
---

# Restore an archived environment

`POST /projects/{projectId}/environments/{environmentId}/restore`

Restore an archived environment. Returns 409 if another live environment took its name in the meantime. Plugin pins whose version row no longer exists at all are dropped on the way back to live — compare the returned `pluginVersionIds` against what you archived to detect that. Requires `expectedRevision` — the revision you last read. If the environment changed since, the write is rejected with 409 rather than overwriting the concurrent edit. Requires project admin.

## Path parameters

- `projectId` string, required
- `environmentId` string, required

## Request body

- ProjectEnvironmentRevisionRequest — The optimistic-concurrency precondition. Unknown fields are rejected.
  - `expectedRevision` integer, required — The `revision` you last read for this environment.

## Response `200`

The updated environment.

- ProjectEnvironment — A project environment: a named, live-editable execution bundle that eval suites and journeys run against.
  - `id` string, required
  - `projectId` string, required
  - `name` string, required — Unique among the project's live (non-archived) environments.
  - `description` string
  - `hostId` string, required — The host this environment runs against.
  - `serverAttachmentId` string — Present only when the environment pins a standalone server group; otherwise the host config's own servers apply.
  - `skillSelection` EnvironmentSkillSelection — An explicit pinned skill selection. Cannot be empty — clear the field instead (send `null` on update) to mean "no pinned skills".
    - `mode` 'explicit', required
    - `skillIds` string[], required — Project-shared skill IDs. Skills carrying supporting files or extra frontmatter, and plugin-component skills, cannot be pinned.
  - `pluginVersionIds` string[] — Pinned plugin VERSION IDs. Narrow by design: the plugin must be installed and enabled, the version must be `ready`, at most one version per plugin may be pinned, and none of its skills may carry supporting files. Not a general-purpose plugin list.
  - `sandboxImageId` string — Sandbox-image pin: a project-shared image (see the images endpoints) that eval runs in this environment boot a fresh sandbox from. Absent when unpinned.
  - `revision` integer, required — Optimistic-concurrency counter. Pass this back as `expectedRevision` on the next write; if it no longer matches, the write is rejected with 409 instead of overwriting a concurrent edit.
  - `archived` boolean, required — Archived environments cannot be edited or launched until restored.
  - `archivedAt` number — Unix epoch milliseconds. Present only when archived.
  - `createdAt` number, required — Unix epoch milliseconds.
  - `updatedAt` number, required — Unix epoch milliseconds.

## Other responses

- `400` — Malformed body or parameters.
- `401` — Missing, invalid, revoked, or orphaned key (`UNAUTHORIZED`) — or the **target MCP server** needs an OAuth grant (`OAUTH_REQUIRED`), which is a property of the server, not your key.
- `403` — Key is valid but not allowed to do this.
- `404` — Unknown project, server, or resource.
- `409` — The resource is not in a state that accepts this write — a stale `expectedRevision`, a duplicate name, or an environment that cannot currently be launched. The request was well-formed; re-read the resource and retry.
- `429` — Per-key rate limit exceeded (60 requests/minute sustained, bursts up to 10). Honor `Retry-After` and back off with jitter.
- `500` — Something failed on MCPJam's side.
- `502` — Could not connect to the target MCP server.

---

[API](https://skmtc.net/mcpjam/apis/mcpjam-api.md) · [All operations](https://skmtc.net/mcpjam/apis/mcpjam-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/mcpjam/mcpjam-api/versions/b767df188d0c/schema)
