Workflows

Running Workflows via the API

Every workflow you can run from the Versus UI can also be run over the REST API — so you can launch and supervise automation from a CI pipeline, a change system, a cron job, or your own tooling. This guide is generic: it applies to any workflow — upgrades, certificate renewals, firewall changes, migrations, custom scripts — not one specific playbook.

The API lets you do four things, which map to the four parts of this guide:

  1. Authenticate — exchange credentials for a bearer token.
  2. Discover — list workflows and inspect their sections and inputs.
  3. Run — trigger a workflow, optionally one section at a time.
  4. Supervise — poll status, approve gates, retry steps, and back out.

All endpoints are under your Versus base URL, e.g. https://versus.example.com/api/…

1 · Authenticate

The API uses JWT bearer tokens. Exchange a username / password for an access token:

POST /api/auth/token/
Content-Type: application/json

{ "username": "svc-automation", "password": "••••••••" }

── 200 OK ──
{ "access": "eyJhbGc…", "refresh": "eyJhbGc…" }

Send the access token on every subsequent request:

Authorization: Bearer eyJhbGc…

Access tokens last 8 hours; refresh with POST /api/auth/token/refresh/ ({ "refresh": "…" }) to get a new access token without re-sending credentials. Use a dedicated service account for automation, scoped by RBAC to only what it needs. If the account has MFA enforced, complete the TOTP challenge (/api/auth/totp/verify/) as part of obtaining the token.

2 · Discover workflows

List the workflows available to you:

GET /api/workflows/

Each entry includes its id, name, slug, category, and graph (the nodes and sections that make up the flow). Fetch one to inspect its structure and any inputs it expects:

GET /api/workflows/{id}/

Workflows are organized into sections — labelled groups of steps (for example Pre-checks, Apply, Verify). Sections are what let you run a workflow in controlled stages (see §3). The full catalog of step types is available at GET /api/workflow-steps/.

3 · Run a workflow

There are two ways to start a run. Use whichever fits your caller.

A · Trigger by name (recommended for external callers)

POST /api/workflow-trigger/ resolves everything by human-readable identifiers, so your script doesn't need to look up database IDs:

POST /api/workflow-trigger/
Authorization: Bearer …
Content-Type: application/json

{
  "workflow":           "NetScaler Upgrade",   // workflow name or slug (case-insensitive)
  "device_group":       "ns-pair-1",           // target device group by name
  "run_name":           "Nightly upgrade",     // optional label
  "stop_after_section": 0,                      // optional: pause after section 0
  "context":            { }                     // any extra workflow inputs
}

── 201 Created ──
{ "run_id": 42, "status": "pending", "status_url": "/api/workflow-status/42/" }

Some workflow families accept convenience fields — e.g. an upgrade can take firmware_version (and optionally vendor), which Versus resolves to the right firmware image and injects into the run context for you. Anything else your workflow reads goes in context.

B · Run by ID

If you already have the workflow's numeric ID, post directly to it:

POST /api/workflows/{id}/run/
{ "device_group": 7, "name": "Nightly upgrade", "context": { } }
NoteChange gating. If a workflow is configured to run under a Versus Desk change window, triggering it creates a Change ticket instead of starting immediately — the run begins only once that change is approved and scheduled. The API returns the run in pending; poll its status to see when it starts.

Running one section at a time

This is the key to safe, staged execution. Pass stop_after_section: N (0-based) to run up to and including section N, then pause. For example, stop_after_section: 0 runs only the first section (say, Pre-checks) and stops.

When you're ready to continue, advance the run with resume:

POST /api/workflow-runs/{run_id}/resume/
{ "stop_after_section": 1 }     // run through section 1, then pause again

Omit stop_after_section on resume to run the rest of the workflow to completion. This lets you gate each stage behind your own checks — run pre-checks via the API, validate the result in your pipeline, then release the Apply section, then Verify, each with its own resume call.

4 · Supervise a run

Poll status

GET /api/workflow-status/{run_id}/

Returns the run broken down by section → step → device, with timing, per-step status, and — for any failed step — an extracted error snippet and AI-generated resolution guidance. Poll this until the run reaches a terminal status (completed, failed, cancelled) or pauses (waiting_approval, paused).

For the raw run object (including step_runs with their IDs, which you need for step-level actions below), use GET /api/workflow-runs/{run_id}/. List and filter runs with GET /api/workflow-runs/?workflow=&status=&device_group=.

Approvals

If a workflow contains an Approval node, the run pauses at waiting_approval. Clear it:

POST /api/workflow-runs/{run_id}/resume_approval/
{ "approved": true, "comment": "Change CR-1234 approved" }

Send "approved": false to reject and stop the run.

Retry, resume, and control

ActionEndpointBody
Pause a running runPOST /api/workflow-runs/{id}/pause/—
Resume / advance sectionsPOST /api/workflow-runs/{id}/resume/stop_after_section?
Cancel a runPOST /api/workflow-runs/{id}/cancel/—
Retry a failed stepPOST /api/workflow-runs/{id}/retry_step/{ step_run_id }
Resume a failed runPOST /api/workflow-runs/{id}/resume_failed/—
Mark a step completePOST /api/workflow-runs/{id}/mark_complete/{ step_run_id }

Step-level actions take a step_run_id, which you read from GET /api/workflow-runs/{id}/.

Back-out

If a run made changes you need to reverse, request a back-out plan — Versus generates the compensating steps for what ran:

POST /api/workflow-runs/{run_id}/request_backout/
{ "step_run_ids": [ … ] }   // optional; omit to back out the whole run

Retrieve it with GET /api/workflow-runs/{run_id}/backout/.

Putting it together

A typical staged, API-driven change looks like this:

  1. POST /api/auth/token/ → get a bearer token.
  2. POST /api/workflow-trigger/ with stop_after_section: 0 → run pre-checks, get run_id.
  3. Poll GET /api/workflow-status/{run_id}/ until it pauses; validate the pre-check results in your pipeline.
  4. POST /api/workflow-runs/{run_id}/resume/ (no stop_after_section) → release the rest.
  5. Poll to completion; on a failed step, retry_step, or request_backout to reverse.

Because the same runs appear in the Versus UI, an operator can watch, intervene, or take over at any point — the API and the console act on the same workflow run.

Related