Skip to content
SSalesShiftDocs
API reference

Workflows

Visual workflows, their nodes and edges, validation, test runs and run history.

14 endpoints· 2 called live· 12 not exercised here· verified against http://127.0.0.1:8741

14 endpoints

GET/api/v1/salesshift/workflow-runs/{run_id}Not exercised hereOne workflow run with its per-node step log.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
run_idstring(uuid)required

Request

curl
curl 'https://api.vxcloud.io/api/v1/salesshift/workflow-runs/{run_id}' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
404Run not found
#get-api-v1-salesshift-workflow-runs-run-idworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:1259Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
GET/api/v1/salesshift/workflowsCalled liveThe organization's workflows, optionally filtered by status.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Query parameters

NameTypeRequiredNotes
statusstring?optional

Request

curl
curl 'https://api.vxcloud.io/api/v1/salesshift/workflows' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Observed shape
{
  "success": "bool",
  "data": [
    {
      "id": "str",
      "name": "str",
      "description": "str",
      "status": "str",
      "trigger_type": "str",
      "trigger_config": {},
      "graph": {
        "nodes": "...",
        "edges": "..."
      },
      "stats": {
        "runs": "...",
        "failed": "...",
        "completed": "...",
        "last_run_at": "..."
      },
      "owner_id": "int",
      "runs_count": "int",
      "created_at": "str",
      "updated_at": "str"
    },
    "...x4"
  ]
}
Observed on 2026-08-06 — keys are real, values are the types that came back.
#get-api-v1-salesshift-workflowsworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:839Called against http://127.0.0.1:8741 on 2026-08-06 with a real JWT; the response matched the shape recorded below.
POST/api/v1/salesshift/workflowsNot exercised hereCreate a workflow with a validated status and trigger type.
Auth
get_org_user
Scope
organization
Success
201 · application/json
Envelope
success+data

Request body (required) — WorkflowCreate

FieldTypeRequiredNotes
namestringrequired≤ 255 chars.
descriptionstring?optional
trigger_typestringoptionalDefault "manual".
trigger_configobject?optional
graphobject?optional
statusstring?optional

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "<string>", "description": "<string>", "trigger_type": "manual", "trigger_config": {}, "graph": {}, "status": "<string>" }'

Response · 201

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#post-api-v1-salesshift-workflowsworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:868Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
GET/api/v1/salesshift/workflows/{workflow_id}Called liveOne workflow with its run count.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request

curl
curl 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Observed shape
{
  "success": "bool",
  "data": {
    "id": "str",
    "name": "str",
    "description": "str",
    "status": "str",
    "trigger_type": "str",
    "trigger_config": {},
    "graph": {
      "nodes": [
        "...",
        "...x6"
      ],
      "edges": [
        "...",
        "...x5"
      ]
    },
    "stats": {
      "runs": "int",
      "failed": "int",
      "completed": "int",
      "last_run_at": "str"
    },
    "owner_id": "int",
    "runs_count": "int",
    "created_at": "str",
    "updated_at": "str"
  }
}
Observed on 2026-08-06 — keys are real, values are the types that came back.
#get-api-v1-salesshift-workflows-workflow-idworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:891Called against http://127.0.0.1:8741 on 2026-08-06 with a real JWT; the response matched the shape recorded below.
PUT/api/v1/salesshift/workflows/{workflow_id}Not exercised hereUpdate a workflow from a partial payload.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request body (required) — WorkflowUpdate

FieldTypeRequiredNotes
namestring?optional
descriptionstring?optional
trigger_typestring?optional
trigger_configobject?optional
graphobject?optional
statusstring?optional

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X PUT 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "<string>", "description": "<string>", "trigger_type": "<string>", "trigger_config": {}, "graph": {}, "status": "<string>" }'

Response · 200

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#put-api-v1-salesshift-workflows-workflow-idworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:904Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
DELETE/api/v1/salesshift/workflows/{workflow_id}Not exercised hereDelete a workflow.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request

curl
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "success": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
404Workflow not found
#delete-api-v1-salesshift-workflows-workflow-idworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:939Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/workflows/{workflow_id}/activateNot exercised hereActivate — but only a graph the engine says is valid goes live.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/activate' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "data": "…",
  "error": "…",
  "success": "…",
  "validation": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
400Add nodes to the canvas before activating
#post-api-v1-salesshift-workflows-workflow-id-activateworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:957Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/workflows/{workflow_id}/duplicateNot exercised hereCopy a workflow, its nodes and its edges into a new draft.
Auth
get_org_user
Scope
organization
Success
201 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/duplicate' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 201

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#post-api-v1-salesshift-workflows-workflow-id-duplicateworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:1014Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/workflows/{workflow_id}/enrollNot exercised hereOne run per contact.

One run per contact. Only ACTIVE workflows accept enrollments.

Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request body (required) — EnrollRequest

FieldTypeRequiredNotes
contact_idsstring(uuid)[]optional

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/enroll' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "contact_ids": [ "<string(uuid)>" ] }'

Response · 200

Top-level keys
{
  "enrolled": "…",
  "run_ids": "…",
  "skipped": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
400Workflow is {...} — activate it before enrolling contacts
400Workflow graph is empty
400contact_ids required
400Max {...} contacts per enrollment
#post-api-v1-salesshift-workflows-workflow-id-enrollworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:1148Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/workflows/{workflow_id}/pauseNot exercised hereSet a workflow's status to paused.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/pause' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#post-api-v1-salesshift-workflows-workflow-id-pauseworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:1000Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
GET/api/v1/salesshift/workflows/{workflow_id}/runsNot exercised hereRecent runs of one workflow.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Query parameters

NameTypeRequiredNotes
limitintegeroptionalDefault 50. min 1. max 200.

Request

curl
curl 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/runs' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#get-api-v1-salesshift-workflows-workflow-id-runsworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:1214Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/workflows/{workflow_id}/test-runNot exercised hereRun the graph once and hand back the full trace for the canvas.

Run the graph once and hand back the full trace for the canvas. With no ``contact_id`` a transient sample contact is used and the run is flagged ``is_sample``. Side effects are simulated unless ``dry_run: false``.

Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request body (optional)

Accepts a JSON object; the source declares no field list.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/test-run' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "dry_run": "…",
  "error": "…",
  "is_sample": "…",
  "run": "…",
  "status": "…",
  "steps": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
400Nothing to run — the canvas is empty
404Contact not found
#post-api-v1-salesshift-workflows-workflow-id-test-runworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:1066Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/workflows/{workflow_id}/validateNot exercised hereProxy the node's graph linter.

Proxy the node's graph linter. Pass a graph to lint unsaved canvas edits.

Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
workflow_idstring(uuid)required

Request body (optional)

Accepts a JSON object; the source declares no field list.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/validate' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "success": "…"
}
Top-level keys read from the handler's return statements.
#post-api-v1-salesshift-workflows-workflow-id-validateworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:1039Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/workflows/internal/actionin-handler-authNot exercised herePerform one side-effecting node on behalf of the Go engine.

Perform one side-effecting node on behalf of the Go engine. Guarded by the run's own callback token (``X-API-Key``) — the engine got it from us when the run started, it dies with the run, and it is stripped from every context this API hands back to the browser.

Auth
no dependency
Scope
in-handler-auth
Success
200 · application/json
Envelope
success+custom

NOT public. Guarded by the run's own callback token sent as X-API-Key and checked by _authorised(run, key); a bad key and an unknown run id both return 401 'Invalid workflow callback credentials' so there is no run-id oracle. The token dies with the run and is stripped from anything handed to the browser.

Request body (required) — InternalActionRequest

FieldTypeRequiredNotes
run_idstring(uuid)required
node_typestringrequired
node_idstring?optional
configobjectoptional
contextobjectoptional

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/internal/action' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "run_id": "<string(uuid)>", "node_type": "<string>", "node_id": "<string>", "config": {}, "context": {} }'

Response · 200

Top-level keys
{
  "error": "…",
  "output": "…",
  "reason": "…",
  "simulated": "…",
  "skipped": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
401Invalid workflow callback credentials
409Run is already {...}
400webhook nodes are performed by the node engine, not the API
400'{...}' is a graph node, not an action — the engine resolves it
400Unsupported action node '{...}' — expected one of {...}
#post-api-v1-salesshift-workflows-internal-actionworkflows_router · vxcloud_fastapiclient/app/services/salesshift/workflows_router.py:1593Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.