Validate Workflow
Validate a workflow definition against the FULL run-start bundle, without saving it.
Runs every gate a run start would apply — validate_definition (structural /
port-contract validation) plus every preflight_definition gate (source/output
completeness, locale routing, translator coverage) — not the narrower save-time
subset POST /workflows and PUT /workflows/{id} use. A definition that saves
cleanly can still fail every one of these; that gap is exactly what this endpoint
exists to close before a definition is ever persisted.
Always returns 200. valid: false with a populated errors list is itself a
successful answer to “is this valid?” — 422 stays reserved for a malformed request
body. A true entitlement refusal (a plan-gated node/provider the caller’s plan
cannot use, ErrorCode.FORBIDDEN) is reported separately in blocked: not fixable
by editing the graph. A voice-ownership violation (unauthorized/unknown/unsupported
voice reference) is ErrorCode.VALIDATION_ERROR instead — an LLM fixes it the same
way it fixes any other rule, by picking a different voice/model — so it is folded
into errors like every other rule violation, not blocked.
No side effects — nothing is read from or written to the workflows table.
Requires at least editor role. Scope is workflows:write deliberately: a caller
who cannot create a workflow should not receive a validation result that exists
only to gate creation.
Authentication
Onepin live API key (op_live_...). Test and public keys are reserved in Phase 1.
Headers
Request
Response
Result of validating a definition against the full run-start bundle, without saving it.
valid reflects errors only — a non-empty blocked does not flip it to False,
since blocked entries are not graph defects (see ValidationBlockedOut).

