neosourceDocs
Search docs

Replace the step snapshot for an in-flight job

POST/api/jobs/{job_id}/steps

upsertJobSteps

Runner-protocol route (same lease-bearer auth as the log chunk POST). The posted list is the full truth for the job's steps: rows are upserted by `(job_id, step_index)` and rows absent from the snapshot are deleted — posting the same snapshot twice is a no-op.

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

curl

curl -X POST 'https://neosource.dev/api/jobs/JOB_ID/steps' \
  -H 'Authorization: Bearer $NEOSOURCE_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"steps":[]}'

fetch

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

Path parameters

job_idrequired

string

Request bodyrequired

application/json

UpsertJobStepsRequest

object

Full-snapshot step upsert (runner-authenticated, same trust envelope as the log-chunk POST). Idempotent: posting the same snapshot twice is a no-op; steps absent from the snapshot are deleted.

stepsrequired

array

items

UpsertJobStepRequest

object

One step in the snapshot the runner posts to `POST /api/jobs/{job_id}/steps`. Timestamps are ms since epoch.

cache
finished_at

integer | nullint64

log_end_offset

integer | nullint64

log_start_offsetrequired

integerint64

namerequired

string

started_at

integer | nullint64

statusrequired
WorkflowRunStepStatus
step_indexrequired

integerint32

Responses

204Snapshot stored

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

Schemas

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

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"

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"