---
title: "Hold a node awake past its idle timer (bills the whole hold)"
method: POST
path: "/preview/nodes/{name}/hold"
tags: ["nodes"]
---

# Hold a node awake past its idle timer (bills the whole hold)

`POST /preview/nodes/{name}/hold`

## Request

- Base URL: `https://autoresearch.sfcompute.com`
- URL: `https://autoresearch.sfcompute.com/preview/nodes/{name}/hold`
- Auth: HTTP bearer

Hold a node awake: stop the idle timer until the time you name, so a node between two pieces of work is not reclaimed while you think. THE HONEST REPLACEMENT for a keepalive sleep loop - a background `while true; do sleep` does the same thing while occupying a detached-command slot, rendering on your mission page as if it were work, and leaving the audit log saying you ran a command when what you did was ask us not to reclaim a node. `until` is required and ceilinged (node_hold_ceiling_hours; list_limits shows it): the node BILLS the whole time at its normal rate, and the response quotes what the full hold costs before you commit to it. Forward-only, like a queue hold: a shorter re-ask never cuts an existing hold, because another agent working this node may be relying on it - release_node is how a hold ends early, and it is explicit. WHICH STOPS THIS DEFEATS: the idle grace reaper, AND the workspace's idle-burn auto-stop (set_alerts) for the length of the hold - the two stops that fire because nothing looks like it is happening. That second one is why a hold is the right tool for zero-GPU work that IS happening: a file transfer, a dependency install, a dataset download. It is a deferral, not an exemption: when the hold ends, an idle node is stopped by the alert as armed. Everything else still lands - a spend cap, an unpaid invoice, an org admin, a host retirement stop a held node. A stop of any kind clears the hold, so it never carries into a later wake. When the hold expires the node is back on its normal idle path: an IDLE node stops on the next sweep, so a hold you forget on an idle node costs what you were quoted and no more - but a node the meter can see WORKING keeps getting a fresh grace window for as long as the work lasts, hold or no hold (get_node's utilization.busy is that verdict), and only stop_node ends that bill. get_node shows a live hold under `hold`. A QUEUED node refuses a hold: set a boot command (run_command on_wake), hold once it runs.

## Path parameters

- `name` string, required: Node name (from `list_nodes`).

## Query parameters

- `workspace` string

## Request body

- object
  - `mission` string, nullable: The mission you are working under (from open_mission), so the hold reads as this investigation's decision rather than your account's.
  - `until` string, required: When the hold ends: a duration from now ("2h", "90m") or an absolute RFC3339 time. REQUIRED - a hold burns a live GPU with nobody watching, so there is no unbounded form and no default that would pick a number for you. Forward-only: a shorter re-ask never cuts a hold, because another agent on this node may be relying on it. Ceilinged by node_hold_ceiling_hours (list_limits).

## Response `200`

The capability's JSON result.

- Result: The capability's result: the same object the MCP tool returns as structuredContent. Resources carry an `object` type discriminator and an immutable id; money is integer micro-dollars in `*_usd_micros` fields.
  - `object` string: The resource type, when the result is one resource.

## Other responses

- `400`: Malformed request: bad JSON, a parameter that does not parse, or a value outside its range. Code `invalid`.
- `401`: No bearer token, or one this API cannot verify. Code `unauthenticated`.
- `403`: Authenticated, but the token's scopes or the account's role do not reach this operation. The message names the scope word to request. Code `forbidden`.
- `404`: No such route. Code `not_found`; the body names the OpenAPI document.
- `422`: A well-formed request the platform declined: no such node, a cap reached, a state that forbids the move. The message says which, and what to do instead. Code `refused`.
- `429`: Over this door's per-customer budget. Wait `Retry-After` seconds. Code `rate_limited`.
- `500`: Our fault. Retry; if it persists, quote the request-id. Code `internal`.

---

[API](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api.md) · [All operations](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/givemeanode/apis/autoresearch-customer-api/revisions/f88dcb70ac6c?raw)
