neosourceDocs
Search docs

List a run's jobs with their step records

GET/api/workflow-runs/{run_id}/jobs

listWorkflowRunJobs

Authentication optional — this operation also accepts anonymous requests. When authenticating, use a bearer token or a session cookie.

curl

curl -X GET 'https://neosource.dev/api/workflow-runs/RUN_ID/jobs' \
  -H 'Authorization: Bearer $NEOSOURCE_TOKEN'

fetch

fetch("https://neosource.dev/api/workflow-runs/RUN_ID/jobs", {
  method: "GET",
  headers: {
    Authorization: "Bearer $NEOSOURCE_TOKEN",
  },
});

Path parameters

run_idrequired

string

Responses

200Jobs with embedded steps

application/json

WorkflowRunJobListResponse

object

Jobs (with embedded steps) of one run (`GET /api/workflow-runs/{run_id}/jobs`).

jobsrequired

array

items

WorkflowRunJobResponse

object

compile_cache
definitionrequired

object

Definition slice the runner needs to execute. JSON shape mirrors `neosource_core::model::WorkflowJobDef`.

enqueued_atrequired

integerint64

executed_on
exit_code

integer | nullint32

finished_at

integer | nullint64

idrequired

string

job_keyrequired

string

log_offsetrequired

integerint64

log_truncated

boolean

The job's log hit its per-job size cap (ADR 0029 §"Log size per job / retention"). The log ends with a server-authored truncation marker line and nothing more will ever be appended. This flag, not that line, is the authoritative signal — a job can echo the same text.

matrix_values

object | null

Matrix combination, when this job row came from matrix expansion.

needsrequired

array

Other jobs that must succeed before this one is eligible.

items

string

repo_idrequired

string

run_idrequired

string

runs_on

array

Labels the job's `runs-on:` requires (a Nix job reports `["nix"]`).

items

string

started_at

integer | nullint64

statusrequired
WorkflowRunJobStatus
steps

array

Per-step records reported by the runner. Empty until the runner posts its first snapshot (and always empty on the claim payload).

403Forbidden — one of: forbidden, needs_scope

application/json

one of
  • ErrorForbidden
  • NeedsScopeError

    object

    `403` body returned when listing private repos but the linked identity lacks the required provider scope. The SPA turns this into an incremental-authorization prompt (Tier 2) that calls the `/elevate` OAuth endpoint with this `scope`.

    errorrequired

    string

    Always `needs_scope` — this body exists to carry the extra fields that kind needs.

    "needs_scope"

    scoperequired

    string

    The provider scope to request via elevation (e.g. `"repo"`).

Standard errors

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

  • 400Bad Request — one of: invalid_input
  • 404Not Found — one of: not_found
  • 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

Schemas

Referenced above. Listed here rather than expanded inline, so the same definition is not repeated at every level.

CompileCacheResponse

object

A job's compile-cache result, as SERVED to a reader: the raw counters plus the two figures derived from them. The derived fields are computed at read time rather than stored, so improving the model never means a migration and the inputs stay visible beside the output. Both are `null` where they have no meaning — notably `estimated_saved_ms` on a job that hit on everything and therefore never measured a compile.

compilationsrequired

integerint64

compile_msrequired

integerint64

estimated_saved_ms

integer | nullint64

Modelled ms the cache saved: `hits × (mean compile − mean cache read)`. `null` when the terms do not exist — see `JobCompileCache`.

hit_rate

number | nulldouble

Hits ÷ (hits + misses), or `null` when there were no requests.

hitsrequired

integerint64

missesrequired

integerint64

read_hit_msrequired

integerint64

requestsrequired

integerint64

RunnerBindingKind

string

Which trust binding a job executed under (ADR 0056 §1/§7). Serialized on the wire and in `workflow_run_jobs.executed_on` as the `snake_case` strings `hosted` / `workspace` / `actor`.

"hosted""workspace""actor"

WorkflowRunJobStatus

string

Lifecycle of an individual job inside a run. Distinct from the run-level status because `needs:` ordering means some jobs are `Waiting` while others are `Running`. The serde `snake_case` strings are the wire vocabulary the API emits (pinned by the `enum_wire_consistency` tests).

"waiting""ready""running""cancelling""succeeded""failed""cancelled""skipped"

WorkflowRunStepResponse

object

One step of a job, reported by the executing runner. Offsets index into the job's log byte stream (`GET /api/jobs/{job_id}/logs`), so the UI can slice the job log per step. `log_end_offset` is `null` while the step is in flight.

cache
one of
  • null

  • StepCacheReportDto

    object

    What a step's cache RESTORE got back. `null` on the step it belongs to means "this step said nothing about caching" — never "miss". Every step that predates the feature, and every step that is not a cache restore, reads null, so a reader that renders absence as a miss libels most of the platform's history.

    bytes

    integer | nullint64

    Compressed size of the restored entry, when the transport knew one.

    matched_key

    string | null

    The key that MATCHED — the primary key on an exact hit, the restore-key-matched entry's key on a partial one. `null` on a miss.

    outcomerequired

    StepCacheOutcome

    string

    What a cache RESTORE got back (ADR 0016; phase 2 of `plans/ci-cache-and-step-visibility-2026-08.md`). Scoped to restores on purpose. A restore is one-to-one with a step, so the fact has an unambiguous owner and an unambiguous meaning — "did the cache help here". A SAVE is not: the combined `actions/cache@v4` saves from a job-end post-hook that runs after every step has finished, so attributing it to a step index would mean inventing one. Adding a save outcome later is additive to this enum and to the column that stores it.

    "exact""partial""miss"

finished_at

integer | nullint64

log_end_offset

integer | nullint64

log_start_offsetrequired

integerint64

namerequired

string

started_at

integer | nullint64

statusrequired

WorkflowRunStepStatus

string

Lifecycle of one step inside a job. Written by the runner (it knows the boundaries exactly) via an idempotent full-snapshot upsert; never derived server-side from log parsing.

"queued""running""succeeded""failed""skipped"

step_indexrequired

integerint32