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.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| run_id | string(uuid) | required |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/workflow-runs/{run_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Run not found |
GET/api/v1/salesshift/workflowsCalled liveThe organization's workflows, optionally filtered by status.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| status | string? | optional |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/workflows' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"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"
]
}POST/api/v1/salesshift/workflowsNot exercised hereCreate a workflow with a validated status and trigger type.
Request body (required) — WorkflowCreate
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | ≤ 255 chars. |
| description | string? | optional | |
| trigger_type | string | optional | Default "manual". |
| trigger_config | object? | optional | |
| graph | object? | optional | |
| status | string? | optional |
Values in the request below are typed placeholders, not sample data.
Request
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
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/workflows/{workflow_id}Called liveOne workflow with its run count.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"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"
}
}PUT/api/v1/salesshift/workflows/{workflow_id}Not exercised hereUpdate a workflow from a partial payload.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request body (required) — WorkflowUpdate
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string? | optional | |
| description | string? | optional | |
| trigger_type | string? | optional | |
| trigger_config | object? | optional | |
| graph | object? | optional | |
| status | string? | optional |
Values in the request below are typed placeholders, not sample data.
Request
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
{
"data": "…",
"success": "…"
}DELETE/api/v1/salesshift/workflows/{workflow_id}Not exercised hereDelete a workflow.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Workflow not found |
POST/api/v1/salesshift/workflows/{workflow_id}/activateNot exercised hereActivate — but only a graph the engine says is valid goes live.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/activate' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"error": "…",
"success": "…",
"validation": "…"
}Errors
| Status | detail |
|---|---|
| 400 | Add nodes to the canvas before activating |
POST/api/v1/salesshift/workflows/{workflow_id}/duplicateNot exercised hereCopy a workflow, its nodes and its edges into a new draft.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/duplicate' \
-H "Authorization: Bearer $SS_TOKEN"Response · 201
{
"data": "…",
"success": "…"
}POST/api/v1/salesshift/workflows/{workflow_id}/enrollNot exercised hereOne run per contact.
One run per contact. Only ACTIVE workflows accept enrollments.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request body (required) — EnrollRequest
| Field | Type | Required | Notes |
|---|---|---|---|
| contact_ids | string(uuid)[] | optional |
Values in the request below are typed placeholders, not sample data.
Request
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
{
"enrolled": "…",
"run_ids": "…",
"skipped": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | Workflow is {...} — activate it before enrolling contacts |
| 400 | Workflow graph is empty |
| 400 | contact_ids required |
| 400 | Max {...} contacts per enrollment |
POST/api/v1/salesshift/workflows/{workflow_id}/pauseNot exercised hereSet a workflow's status to paused.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/pause' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/workflows/{workflow_id}/runsNot exercised hereRecent runs of one workflow.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| limit | integer | optional | Default 50. min 1. max 200. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/runs' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}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``.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request body (optional)
Accepts a JSON object; the source declares no field list.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/test-run' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"dry_run": "…",
"error": "…",
"is_sample": "…",
"run": "…",
"status": "…",
"steps": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | Nothing to run — the canvas is empty |
| 404 | Contact not found |
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.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| workflow_id | string(uuid) | required |
Request body (optional)
Accepts a JSON object; the source declares no field list.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/workflows/{workflow_id}/validate' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "…"
}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.
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
| Field | Type | Required | Notes |
|---|---|---|---|
| run_id | string(uuid) | required | |
| node_type | string | required | |
| node_id | string? | optional | |
| config | object | optional | |
| context | object | optional |
Values in the request below are typed placeholders, not sample data.
Request
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
{
"error": "…",
"output": "…",
"reason": "…",
"simulated": "…",
"skipped": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 401 | Invalid workflow callback credentials |
| 409 | Run is already {...} |
| 400 | webhook nodes are performed by the node engine, not the API |
| 400 | '{...}' is a graph node, not an action — the engine resolves it |
| 400 | Unsupported action node '{...}' — expected one of {...} |