Restore an expired workspace onto a Session
package main
import ( "fmt" "net/http" "io")
func main() {
url := "https://api.vampikez.fun/v1/sessions/9f2b7c14-59d3-4f7a-b8e1-2a6c05d4e731/workspace"
req, _ := http.NewRequest("PUT", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}const url = 'https://api.vampikez.fun/v1/sessions/9f2b7c14-59d3-4f7a-b8e1-2a6c05d4e731/workspace';const options = {method: 'PUT', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://api.vampikez.fun/v1/sessions/9f2b7c14-59d3-4f7a-b8e1-2a6c05d4e731/workspace \ --header 'Authorization: Bearer <token>'Requires wamp.cloud.turns:submit — restoring is exactly what submitting a Turn does implicitly, so no separate authority is invented for it. A sandbox lease is bounded and is released without warning once it lapses. After that, GET /v1/sessions/{sessionId}/repository/review and PUT /v1/sessions/{sessionId}/publications/{publicationId} answer 409 cloud_workspace_expired. This call provisions a new sandbox and replays the Session’s sealed checkpoint into it, so an integration that comes back late can still review and publish.
It has no request body and is idempotent on the postcondition rather than on an id: when the Session already holds a lease with enough time left it is returned unchanged, and repeating the call never stacks sandboxes. The response is the same Session envelope every other Session read returns — read workspace.expiresAt for the deadline you actually got.
Restoration needs a checkpoint, and this endpoint will not pretend otherwise: when the Session reports continuation.canContinue false it answers 409 cloud_resume_unavailable instead of silently starting an empty sandbox on top of lost work. Check continuation first. While the Session’s own Run is bringing its workspace up — a new Session created with its first Turn — this call waits for that bring-up and answers with it, for up to 30 seconds before a 503 cloud_workspace_starting. It also refuses to race the Session’s own lifecycle — 409 cloud_run_in_progress, cloud_publication_in_progress or cloud_session_finalizing mean finish or cancel that first — and a 503 with Retry-After means compute is still starting, not that anything failed. An archived Session is 404: archiving is deliberate and permanent, and its history stays readable without a workspace.
Authorizations
Section titled “Authorizations”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters”A UUID identifying one Cloud resource; Session, Turn, Publication and Merge ids are minted by the caller so an ambiguous retry addresses the same durable command instead of creating a second one.
Example
9f2b7c14-59d3-4f7a-b8e1-2a6c05d4e731A UUID you mint and own; it is the idempotency key for creation and the address of every Turn, artifact and publication underneath
Responses
Section titled “ Responses ”Session with an attached workspace
Envelope returned by every single-Session read and write.
object
The Session as it stands after this request; a create that was an idempotent replay returns the already-stored Session unchanged
object
The caller-owned Session id, unchanged from the create request
Canonical first-party browser URL for handing this Session to a human
Organization that owns the Session; every credential is authorized against this organization
Human-facing name — the supplied title, first non-empty line of initialTurn.message, or New workspace for an idle Session
Correlation metadata supplied at creation; absent when none was sent
object
Stable opaque identifier for the external tenant the work belongs to, not its display name
The caller’s own kind name for the originating record, such as ticket or issue
The caller’s stable opaque id for that record, so a Session can always be traced back to the business object
Stable one-way hash of the external tenant/user pair; never raw PII.
Short human-readable name for the originating record, shown when the Session is handed to a person
HTTPS deep link back to the originating record in the caller’s product
Repository checked out into the sandbox, with the exact base the Session was pinned to; absent for a Session with no repository
object
object
object
A UUID identifying one Cloud resource; Session, Turn, Publication and Merge ids are minted by the caller so an ambiguous retry addresses the same durable command instead of creating a second one.
Lowercase hex 40-character Git object id naming an exact commit or tree in the source repository.
Model in effect for the next Turn; absent when a runtime-managed agent supplies its own default
The settled foreign agent runtime id, such as claude-code or codex; absent means the native WAMP runtime
Sandbox attachment — unavailable when no lease is held, attached with the lease expiresAt, expired once that lease has lapsed; losing it does not end the Session
object
Whether and at what fidelity this Session can be carried into another Run
object
Whether a new Turn can be admitted for this Session — nothing more. It is NOT the answer to “did my previous work survive”: a fresh Session reports canContinue: true with both fidelities none, so a caller that branches on this field alone starts over believing it resumed. reason is the field that answers the other question, and it is present here whenever prior work will not carry. canContinue is false only while state is unavailable.
live while a sandbox lease is still held, fresh before any Run has been accepted, restorable when a sealed checkpoint can be replayed into a new sandbox, unavailable when neither is possible
Fidelity the conversation would be restored at — live in an attached sandbox, exact from a full checkpoint, result_only when just prior results survive, none when nothing does
object
Fidelity the working tree would be restored at — live, portable_tree from a checkpointed tree, or none
object
The Run whose completion sealed the checkpoint this projection describes; absent when no checkpoint exists
Why a next Turn will NOT carry this Session’s previous work. Present exactly when it will not, and absent exactly when it will — so reason == null is the one check that means “resuming here keeps what happened”. no_prior_work accompanies state: fresh and canContinue: true: the Session accepts a Turn and has nothing to carry. The other four accompany state: unavailable and canContinue: false, and name why a restore is impossible rather than merely empty.
Last execution phase the control plane recorded for this Session — a closed set, safe to switch on exhaustively, and additions arrive with a contract change. It remains advisory presentation state: the Run carries the authoritative status, and phase may lag it between a Run’s terminal transition and reconciliation.
Whether a human user or an App installation created the Session, and that actor’s id; an installation-created Session keeps its App authority even when a human later manages it
object
A UUID identifying one Cloud resource; Session, Turn, Publication and Merge ids are minted by the caller so an ambiguous retry addresses the same durable command instead of creating a second one.
Present exactly while this Session has a Run that is not terminal, awaiting included. It is set at admission, so it is already there while the Run is queued or dispatching and before the Run reaches a sandbox or writes its first event — which is the window in which a Turn is refused with 409 cloud_run_in_progress and the Event log is still empty. The one exception is a Run that has ended and is finalizing (phase: finalizing): a follow-up Turn is admitted and queued behind it, and becomes this field. This is the id to cancel, and the id to read GET /v1/sessions/{sessionId}/runs/{runId} with when you did not mint the Turn yourself.
object
A UUID identifying one Cloud resource; Session, Turn, Publication and Merge ids are minted by the caller so an ambiguous retry addresses the same durable command instead of creating a second one.
When the Session was admitted
Last time durable Session state changed; the Session list is ordered by this value descending
Sequence of the newest Event in this Session’s log, 0 before the first. Page GET /v1/sessions/{sessionId}/events only when your cursor is below it
When the Session was archived. Present only on an archived Session — which is readable but closed: it is hidden from the default catalog page, reports continuation.canContinue false with reason session_archived, and rejects every command
Example
{ "session": { "id": "9f2b7c14-59d3-4f7a-b8e1-2a6c05d4e731", "sessionUrl": "https://cloud.wamp.dev/sessions/9f2b7c14-59d3-4f7a-b8e1-2a6c05d4e731", "organizationId": "0b9a6f3e-5c21-4d78-9e64-8f1a2b7c3d05", "title": "Rate limit the payments endpoint", "origin": { "tenantKey": "acme", "objectType": "issue", "objectId": "PAY-4821", "endUserId": "9c1f0a7d4b62e35810af2d6c95b7e043", "label": "PAY-4821 Rate limit the payments endpoint", "url": "https://acme.example.com/issues/PAY-4821" }, "source": { "kind": "github", "grantId": "74c5a903-8e6f-4b1d-a052-3c9e18d7f64b", "label": "acme/checkout-service", "private": true, "baseBranch": "main", "baseOid": "5a3e170c93eda8209e3f5592fe1e1d9976fe26ab" }, "model": "claude-opus-5", "runtime": "wamp", "workspace": { "state": "attached", "expiresAt": "2026-08-12T13:05:44Z" }, "continuation": { "canContinue": true, "state": "live", "conversation": { "fidelity": "live" }, "workspace": { "fidelity": "live" } }, "phase": "provisioning", "createdBy": { "kind": "app_installation", "id": "e3f7b219-6c40-4a8e-b591-07d2c48f3a65" }, "createdAt": "2026-08-12T09:20:14Z", "updatedAt": "2026-08-12T12:05:44Z", "lastEventSequence": 73, "environment": null, "parent": null }}Malformed request
Failure body returned with every non-2xx JSON response; branch on the machine code, never on prose or on the HTTP status alone.
object
Stable machine code
The installation capability the presented credential lacks, returned with insufficient_scope so an integrator knows exactly which capability to request
Advisory seconds to wait before retrying; returned on rate-limit denials, where the Retry-After header carries the same value
Returned with invalid_request: one entry per field of the request body or query that was refused. The WAMP Account API sends the same two keys under the same field name, and no others are sent by either.
object
Field path, outermost segment first. An integer segment is an array index.
Short reason the field was refused. Prose for a human to read; branch on the code and the path, never on this.
Returned with invalid_path_parameter: the name of the path segment that is not a valid id, such as sessionId or artifactId
Returned with unsupported_media_type: the Content-Type you sent, echoed back. Omitted when the request carried a body and no Content-Type at all, which is the same refusal. Request bodies are read only under application/json and RFC 6839 application/*+json; anything else is never parsed, so no field of it was ever seen.
Returned with method_not_allowed: the methods this path does answer, the same list as the Allow header on the response. Read the header if you want one code path for every 405 on the API.
The winning approval decision on 409 cloud_interaction_conflict, when an answer exists; absent for a closed or expired request without an answer
object
Example
{ "error": "invalid_request"}No bearer was presented (bearer_credential_required), or the one presented is expired, revoked or for another audience (invalid_or_expired_credential)
Failure body returned with every non-2xx JSON response; branch on the machine code, never on prose or on the HTTP status alone.
object
Stable machine code
The installation capability the presented credential lacks, returned with insufficient_scope so an integrator knows exactly which capability to request
Advisory seconds to wait before retrying; returned on rate-limit denials, where the Retry-After header carries the same value
Returned with invalid_request: one entry per field of the request body or query that was refused. The WAMP Account API sends the same two keys under the same field name, and no others are sent by either.
object
Field path, outermost segment first. An integer segment is an array index.
Short reason the field was refused. Prose for a human to read; branch on the code and the path, never on this.
Returned with invalid_path_parameter: the name of the path segment that is not a valid id, such as sessionId or artifactId
Returned with unsupported_media_type: the Content-Type you sent, echoed back. Omitted when the request carried a body and no Content-Type at all, which is the same refusal. Request bodies are read only under application/json and RFC 6839 application/*+json; anything else is never parsed, so no field of it was ever seen.
Returned with method_not_allowed: the methods this path does answer, the same list as the Allow header on the response. Read the header if you want one code path for every 405 on the API.
The winning approval decision on 409 cloud_interaction_conflict, when an answer exists; absent for a closed or expired request without an answer
object
Example
{ "error": "bearer_credential_required"}Live installation, scope or organization policy denies the operation
Failure body returned with every non-2xx JSON response; branch on the machine code, never on prose or on the HTTP status alone.
object
Stable machine code
The installation capability the presented credential lacks, returned with insufficient_scope so an integrator knows exactly which capability to request
Advisory seconds to wait before retrying; returned on rate-limit denials, where the Retry-After header carries the same value
Returned with invalid_request: one entry per field of the request body or query that was refused. The WAMP Account API sends the same two keys under the same field name, and no others are sent by either.
object
Field path, outermost segment first. An integer segment is an array index.
Short reason the field was refused. Prose for a human to read; branch on the code and the path, never on this.
Returned with invalid_path_parameter: the name of the path segment that is not a valid id, such as sessionId or artifactId
Returned with unsupported_media_type: the Content-Type you sent, echoed back. Omitted when the request carried a body and no Content-Type at all, which is the same refusal. Request bodies are read only under application/json and RFC 6839 application/*+json; anything else is never parsed, so no field of it was ever seen.
Returned with method_not_allowed: the methods this path does answer, the same list as the Allow header on the response. Read the header if you want one code path for every 405 on the API.
The winning approval decision on 409 cloud_interaction_conflict, when an answer exists; absent for a closed or expired request without an answer
object
Example
{ "error": "insufficient_scope", "requiredScope": "wamp.cloud.sessions:create"}The resource is missing or inaccessible
Failure body returned with every non-2xx JSON response; branch on the machine code, never on prose or on the HTTP status alone.
object
Stable machine code
The installation capability the presented credential lacks, returned with insufficient_scope so an integrator knows exactly which capability to request
Advisory seconds to wait before retrying; returned on rate-limit denials, where the Retry-After header carries the same value
Returned with invalid_request: one entry per field of the request body or query that was refused. The WAMP Account API sends the same two keys under the same field name, and no others are sent by either.
object
Field path, outermost segment first. An integer segment is an array index.
Short reason the field was refused. Prose for a human to read; branch on the code and the path, never on this.
Returned with invalid_path_parameter: the name of the path segment that is not a valid id, such as sessionId or artifactId
Returned with unsupported_media_type: the Content-Type you sent, echoed back. Omitted when the request carried a body and no Content-Type at all, which is the same refusal. Request bodies are read only under application/json and RFC 6839 application/*+json; anything else is never parsed, so no field of it was ever seen.
Returned with method_not_allowed: the methods this path does answer, the same list as the Allow header on the response. Read the header if you want one code path for every 405 on the API.
The winning approval decision on 409 cloud_interaction_conflict, when an answer exists; absent for a closed or expired request without an answer
object
Example
{ "error": "cloud_session_not_found"}Idempotency, lifecycle, revision or single-flight conflict
Failure body returned with every non-2xx JSON response; branch on the machine code, never on prose or on the HTTP status alone.
object
Stable machine code
The installation capability the presented credential lacks, returned with insufficient_scope so an integrator knows exactly which capability to request
Advisory seconds to wait before retrying; returned on rate-limit denials, where the Retry-After header carries the same value
Returned with invalid_request: one entry per field of the request body or query that was refused. The WAMP Account API sends the same two keys under the same field name, and no others are sent by either.
object
Field path, outermost segment first. An integer segment is an array index.
Short reason the field was refused. Prose for a human to read; branch on the code and the path, never on this.
Returned with invalid_path_parameter: the name of the path segment that is not a valid id, such as sessionId or artifactId
Returned with unsupported_media_type: the Content-Type you sent, echoed back. Omitted when the request carried a body and no Content-Type at all, which is the same refusal. Request bodies are read only under application/json and RFC 6839 application/*+json; anything else is never parsed, so no field of it was ever seen.
Returned with method_not_allowed: the methods this path does answer, the same list as the Allow header on the response. Read the header if you want one code path for every 405 on the API.
The winning approval decision on 409 cloud_interaction_conflict, when an answer exists; absent for a closed or expired request without an answer
object
Example
{ "error": "cloud_session_conflict"}The pre-authentication edge budget or durable human-membership/App-installation budget is exhausted
Failure body returned with every non-2xx JSON response; branch on the machine code, never on prose or on the HTTP status alone.
object
Stable machine code
The installation capability the presented credential lacks, returned with insufficient_scope so an integrator knows exactly which capability to request
Advisory seconds to wait before retrying; returned on rate-limit denials, where the Retry-After header carries the same value
Returned with invalid_request: one entry per field of the request body or query that was refused. The WAMP Account API sends the same two keys under the same field name, and no others are sent by either.
object
Field path, outermost segment first. An integer segment is an array index.
Short reason the field was refused. Prose for a human to read; branch on the code and the path, never on this.
Returned with invalid_path_parameter: the name of the path segment that is not a valid id, such as sessionId or artifactId
Returned with unsupported_media_type: the Content-Type you sent, echoed back. Omitted when the request carried a body and no Content-Type at all, which is the same refusal. Request bodies are read only under application/json and RFC 6839 application/*+json; anything else is never parsed, so no field of it was ever seen.
Returned with method_not_allowed: the methods this path does answer, the same list as the Allow header on the response. Read the header if you want one code path for every 405 on the API.
The winning approval decision on 409 cloud_interaction_conflict, when an answer exists; absent for a closed or expired request without an answer
object
Example
{ "error": "cloud_rate_limit_exceeded", "retryAfterSeconds": 3}Headers
Section titled “Headers”IETF HTTPAPI structured quota policy
IETF HTTPAPI structured current service limit
The request was accepted and something on our side failed while answering it. Nothing about the request needs to change; the same call may succeed on retry. Retry cautiously, with backoff — a non-idempotent command may have taken effect before the fault.
Failure body returned with every non-2xx JSON response; branch on the machine code, never on prose or on the HTTP status alone.
object
Stable machine code
The installation capability the presented credential lacks, returned with insufficient_scope so an integrator knows exactly which capability to request
Advisory seconds to wait before retrying; returned on rate-limit denials, where the Retry-After header carries the same value
Returned with invalid_request: one entry per field of the request body or query that was refused. The WAMP Account API sends the same two keys under the same field name, and no others are sent by either.
object
Field path, outermost segment first. An integer segment is an array index.
Short reason the field was refused. Prose for a human to read; branch on the code and the path, never on this.
Returned with invalid_path_parameter: the name of the path segment that is not a valid id, such as sessionId or artifactId
Returned with unsupported_media_type: the Content-Type you sent, echoed back. Omitted when the request carried a body and no Content-Type at all, which is the same refusal. Request bodies are read only under application/json and RFC 6839 application/*+json; anything else is never parsed, so no field of it was ever seen.
Returned with method_not_allowed: the methods this path does answer, the same list as the Allow header on the response. Read the header if you want one code path for every 405 on the API.
The winning approval decision on 409 cloud_interaction_conflict, when an answer exists; absent for a closed or expired request without an answer
object
Example
{ "error": "internal_error"}A retryable condition: a workspace, runtime or provider that is not available yet, or service_unavailable while the service restarts for a release or its database cannot serve the request in time. Retry after the Retry-After this response carries.
Failure body returned with every non-2xx JSON response; branch on the machine code, never on prose or on the HTTP status alone.
object
Stable machine code
The installation capability the presented credential lacks, returned with insufficient_scope so an integrator knows exactly which capability to request
Advisory seconds to wait before retrying; returned on rate-limit denials, where the Retry-After header carries the same value
Returned with invalid_request: one entry per field of the request body or query that was refused. The WAMP Account API sends the same two keys under the same field name, and no others are sent by either.
object
Field path, outermost segment first. An integer segment is an array index.
Short reason the field was refused. Prose for a human to read; branch on the code and the path, never on this.
Returned with invalid_path_parameter: the name of the path segment that is not a valid id, such as sessionId or artifactId
Returned with unsupported_media_type: the Content-Type you sent, echoed back. Omitted when the request carried a body and no Content-Type at all, which is the same refusal. Request bodies are read only under application/json and RFC 6839 application/*+json; anything else is never parsed, so no field of it was ever seen.
Returned with method_not_allowed: the methods this path does answer, the same list as the Allow header on the response. Read the header if you want one code path for every 405 on the API.
The winning approval decision on 409 cloud_interaction_conflict, when an answer exists; absent for a closed or expired request without an answer
object
Example
{ "error": "cloud_workspace_unavailable"}