Docs
Search docs

Upsert a workflow definition

POST/api/workflows

upsertWorkflow

Authentication is not described for this operation in the spec — that does not mean it is public. Check tokens and scopes.

curl

curl -X POST 'https://neosource.dev/api/workflows' \
  -H 'Content-Type: application/json' \
  -d '{"repo_id":"string","path":"string","source_operation":"string","definition":{}}'

fetch

fetch("https://neosource.dev/api/workflows", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"repo_id":"string","path":"string","source_operation":"string","definition":{}}),
});

Request bodyrequired

application/json

UpsertWorkflowRequest

object

definitionrequired

object

Parsed `WorkflowDef`. JSON shape mirrors `neosource_core::model::WorkflowDef`.

pathrequired

string

Path within the repo (`.neosource/workflows/<name>.yml`).

repo_idrequired

string

Repo the workflow belongs to (UUID hex).

source_operationrequired

string

Hex-encoded 32-byte content-addressed operation id that the definition was extracted at.

Responses

200Workflow

application/json

WorkflowResponse

object

check_contexts

array

Available canonical check contexts for this workflow's jobs. Matrix jobs expose their base aggregate context, not individual legs. These names do not promise that the workflow runs on any particular commit.

items

string

created_atrequired

integerint64

dispatch
one of
  • WorkflowDispatchResponse

    object

    A workflow's `on: workflow_dispatch` declaration, as the "Run workflow" form needs it.

    inputsrequired

    array

    Declared inputs, alphabetical by name (the stored definition does not preserve YAML order, so no client should expect it). Empty for a bare `on: workflow_dispatch`.

  • null

idrequired

string

namerequired

string

The `name:` declared in the workflow YAML, for display. A file that failed to parse is named after itself (e.g. `broken.yml`), so this is always something showable. This, `dispatch`, and `check_contexts` are the only projections of the parsed definition on the wire. The full `WorkflowDef` used to be returned here and reached ~100 KB per request on a real repo while every client read just the name; the runner gets definitions through the job-claim path, not this listing.

pathrequired

string

repo_idrequired

string

source_operationrequired

string

updated_atrequired

integerint64

warningsrequired

array

Parse diagnostics recorded when the file was indexed: unknown GHA keys / unsupported triggers ignored with `severity: "warning"`, or a whole-file parse failure as `severity: "error"` (such a workflow is stored inert — no triggers, no jobs — and never runs). Empty when the file parsed clean.

items

WorkflowWarning

object

A non-fatal diagnostic collected while parsing workflow YAML. GHA's own forward-compat posture: a valid-but-unmodeled key (`permissions:`, `concurrency:`, `defaults:`, …) must not fail the whole file — it is ignored and reported. Persisted alongside the indexed workflow (`workflows.warnings`) so the API/UI can surface "this workflow has warnings / failed to parse" instead of the file silently ceasing to exist.

locationrequired

string

Where in the document: `workflow`, `on.push`, `job 'build'`, `job 'build' step 2 ('Deploy')`, …

messagerequired

string

severityrequired
WorkflowWarningSeverity

403Forbidden — one of: forbidden, needs_scope

application/json

one of
  • ErrorForbidden
  • NeedsScopeError

    object

    `403` body returned when a classic OAuth token is asked for something its granted scopes do not cover — an explicit private listing without `repo`, or the one-click GitHub mirror without `admin:public_key`. `scope` names the missing grant so the client can say exactly what the token lacks. There is no elevation route to widen it any more (a re-link goes through the GitHub App, whose tokens carry no scopes), so the client's answer is to say so, never to start a handshake.

    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
  • 409Conflict — one of: already_exists, 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.

WorkflowDispatchInputResponse

object

One declared `workflow_dispatch` input. Mirrors `neosource_core::model::WorkflowDispatchInput` plus its name.

default

string | null

The YAML `default:`, always a string; the server coerces it to the declared type when the input is not submitted.

description

string | null

namerequired

string

The key under `inputs:` — what the dispatch body and `${{ inputs.<name> }}` refer to it by.

options

array

The `options:` of a `choice` input; empty otherwise.

items

string

required

boolean

typerequired

WorkflowDispatchInputType

string

The declared `type:` of a `workflow_dispatch` input — GitHub's closed set. It decides how a submitted value is coerced ([`resolve_dispatch_inputs`]) and which form control the SPA renders. `Environment` behaves exactly as `String` everywhere — neosource has no deployment environments — and is modelled only so the YAML parses without a warning and the form can label it. The serde `snake_case` strings are the wire vocabulary (pinned by the `enum_wire_consistency` tests).

"string""choice""boolean""number""environment"

WorkflowWarningSeverity

string

Severity of a [`WorkflowWarning`].

"warning""error"