neosourceDocs
Search docs

Register a runner

POST/api/runners

registerRunner

Requires authentication using a bearer token — see tokens and scopes.

curl

curl -X POST 'https://neosource.dev/api/runners' \
  -H 'Authorization: Bearer $NEOSOURCE_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"scope":"string","labels":[],"vm_backend":"string"}'

fetch

fetch("https://neosource.dev/api/runners", {
  method: "POST",
  headers: {
    Authorization: "Bearer $NEOSOURCE_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"scope":"string","labels":[],"vm_backend":"string"}),
});

Request bodyrequired

application/json

RegisterRunnerRequest

object

actor_bound

boolean

Bind this runner to the registering account (ADR 0056): it then only claims jobs of runs *triggered by* that account. Needs only workspace membership (workspace-bound registration stays admin-only). The bound account is always the authenticated caller — never chosen by the request.

ephemeral

boolean

Session runner (`neo push --runner`, ADR 0056 §5): registered for one push, deregistered on exit, swept server-side when its presence goes stale. Only meaningful for self-hosted scopes; rejected for hosted registrations.

labelsrequired

array

items

string

scoperequired

RunnerScope

string

Whether a runner is hosted by the platform (per [ADR 0014]) or long-poll-attached from outside.

"hosted""self_hosted""local"

vm_backendrequired

VmBackendKind

string

"docker_shell""kata_clh""kata_fc""lib_krun""k8s_runc"

workspace_id

string | null

Optional workspace association (self-hosted runners typically pin to one).

Responses

201Runner registered

application/json

RunnerResponse

object

actor_id

string | null

Actor binding (ADR 0056): the account whose runs this runner is restricted to, or `null` for workspace-bound / hosted runners.

created_atrequired

integerint64

idrequired

string

labelsrequired

array

items

string

last_seenrequired

integerint64

scoperequired

RunnerScope

string

Whether a runner is hosted by the platform (per [ADR 0014]) or long-poll-attached from outside.

"hosted""self_hosted""local"

statusrequired

RunnerStatus

string

"online""draining""offline"

tokenrequired

string

Per-runner bearer token, `nsr_<hex>`. Returned **exactly once** in the `POST /api/runners` registration response — only its hash is stored server-side, so it can never be re-read. The agent persists it and presents it as `Authorization: Bearer <token>` on every claim / heartbeat / complete / log call.

vm_backendrequired

VmBackendKind

string

"docker_shell""kata_clh""kata_fc""lib_krun""k8s_runc"

workspace_id

string | null

Standard errors

Bodies documented once for the whole API — see standard errors.

  • 400Bad Request — one of: invalid_input
  • 401Authentication required
  • 403Forbidden — one of: forbidden
  • 404Not Found — one of: not_found
  • 409Conflict — one of: conflict
  • 429Rate limited — retry after the `Retry-After` header
  • 500Internal server error
  • 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
  • 504Gateway timeout — the request exceeded the server's handling budget