---
title: "Offboard an interruptible node, now or at a deadline (a termination notice)"
method: POST
path: "/v1/orgs/{orgId}/provider/nodes/{nodeId}/offboard"
tags: ["Provider"]
---

# Offboard an interruptible node, now or at a deadline (a termination notice)

`POST /v1/orgs/{orgId}/provider/nodes/{nodeId}/offboard`

Moves an interruptible node to draining at once and removes it at the deadline: terminateAt, or now plus noticeSeconds, or now when neither is given (send {}). A deadline only ever moves earlier, so repeating or replaying the call is safe. Use it to pass on a reclaim warning from the market the container runs in, or to take a node out yourself. Persistent nodes are offboarded with `orl provider node update --status removed`.

## Path parameters

- `orgId` string, required
- `nodeId` string, required

## Request body

- TerminationNotice — A termination notice: name the deadline with terminateAt or noticeSeconds, not both. Neither means now on offboard, and the token's noticeSeconds on a node's own notice (POST /v1/nodes/termination-notice, the same body).
  - `noticeSeconds` integer — Remove the node this many seconds from now (at most 24 h).
  - `terminateAt` string, date-time — Remove the node at this time (RFC 3339, at most 24 h ahead; a past time means now).

## Response `200`

OK

- ProviderNode
  - `cpuCores` integer, nullable
  - `cpuModel` string, nullable
  - `createdAt` string, required
  - `diskFreeGb` integer, nullable — Free GB on the node's VM/pod data directory, from its last heartbeat. null when the node has no live tunnel: unknown, not zero free.
  - `diskTotalGb` integer, nullable — Total GB of the node's VM/pod data directory, from its last heartbeat. null when the node has no live tunnel: unknown, not zero capacity.
  - `gpus` NodeGpuItem[], required
    - `gpuName` string, required
    - `quantity` integer, required
    - `vramGb` integer, required
  - `hostname` string, required
  - `id` string, required
  - `locationCity` string, nullable
  - `locationCountry` string, nullable
  - `nodeType` string, required
  - `noticeSeconds` integer, nullable — Interruptible nodes only: the notice applied to a termination notice that names no deadline.
  - `ramGb` integer, nullable
  - `reservation` NodeReservationSummary — Reservation state of this node, from the caller's point of view. Present only when some of the node's GPU units are reserved.
    - `releasedUnitCount` integer, required — GPU units this node's reservations have released to the spot market. They are still the reservation's capacity: anyone may buy them, but only at tier=spot, and the capacity owner can reclaim them at any time.
    - `reservations` NodeReservation[]
      - `allowedOrgIds` string[], required — The audience: orgs that may place workloads on the reserved units.
      - `contractRef` string
      - `createdAt` string
      - `endsAt` string — Absent = open-ended until cancelled
      - `id` string, required
      - `managingOrgIds` string[] — Orgs that may release these units to the market, reclaim them, and terminate the spot workloads on them, on the node owner's behalf, while the reservation is active and inside its term. Being in the audience does not confer this.
      - `nodeId` string, required
      - `reason` string
      - `releasedUnitIds` string[] — The subset of reservedUnitIds currently on the spot market (double sell). Still this reservation's capacity, sellable to anyone at tier=spot only, and reclaimable at any time.
      - `reservedUnitIds` string[], required
      - `skipped` string[] — Reclaim only: VM ids left running because they are not spot.
      - `startsAt` string, required
      - `status` 'pending' | 'active' | 'expired' | 'cancelled' | 'needs-review', required — needs-review means the node's GPU topology changed under the reservation: it grants nothing (and withholds its units from everyone) until an operator re-affirms it.
      - `terminated` string[] — Reclaim only: spot VM ids terminated to free the reclaimed units.
      - `topologyGen` integer — Node topology generation this reservation was written against
      - `updatedAt` string
      - `wouldSkip` string[] — Reclaim dry run only: VM ids that would be left running.
      - `wouldTerminate` string[] — Reclaim dry run only: the spot VM ids this call would terminate.
    - `reservedUnitCount` integer, required — GPU units held exclusively for the audience right now
  - `runtime` string — Node runtime: qemu (VFIO VM host), runc (GPU-container Pod node) or process (an interruptible container). Empty reads as qemu.
  - `status` string, required
  - `tdxEnabled` boolean, required
  - `terminateAt` string, nullable — Interruptible nodes only: when the node is removed, set by a termination notice or offboard. null when none is scheduled.

## Other responses

- `400` — The request is invalid
- `401` — Missing or invalid API key
- `403` — The caller is authenticated but may not do this. The caller's role or the API key's scope does not allow it, or the request targets another organization (FORBIDDEN, or NOT_A_MEMBER for a session), or the organization is suspended pending review (ORG_SUSPENDED) or has been deleted (ORG_DISABLED). A new API key or a wider scope clears neither of the last two; see [Account and balance refusals](https://docs.openrelay.inc/docs/errors#account-and-balance-refusals).
- `404` — Resource not found
- `409` — The node is not an interruptible node (NOT_INTERRUPTIBLE). Offboarding an already removed node returns 200 with the node as it is.

## Changes

- **2026-09-30** `15d2bb87d95c` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/openrelay/apis/openrelay-api/changes/v1/orgs/:orgId/provider/nodes/:nodeId/offboard/post.md)

---

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