Skip to main content

Workflow API Documentation

A Workflow in ScriptRun is a visual representation of a process or automation. It consists of interconnected nodes (steps, triggers, actions, outputs) and edges (connections between nodes), allowing you to design and execute complex logic flows.

Key Concepts

  • Workflow: A schema consisting of nodes and edges that defines the sequence of actions.
  • Node: A step in the process (e.g., trigger, LLM request, data processing, output). Each node has a unique UUID identifier.
  • Edge: Connects two nodes, defining the direction of the flow.
  • Data: The structure describing all nodes, edges, the start node, and viewport parameters.
  • WorkflowRun: A single execution instance of a workflow. Has its own UUID, status, and result.

Workflow Data Structure Example

The example below is based on a real workflow: Trigger → If/Else → two LLM branches.

{
"id": 65,
"project": 12,
"title": "Text Classification Workflow",
"data": {
"edges": [
{
"id": "xy-edge__052af1cb-86fd-443a-bc25-626c365025db-0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8",
"type": "custom-edge",
"style": { "stroke": "#76A9FA", "strokeWidth": 2 },
"source": "052af1cb-86fd-443a-bc25-626c365025db",
"target": "0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8",
"animated": false,
"markerEnd": "edge-target",
"markerStart": "edge-source"
},
{
"id": "xy-edge__0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8condition-true-58a35684-7d25-4dff-b012-609eab065751",
"type": "custom-edge",
"style": { "stroke": "#76A9FA", "strokeWidth": 2 },
"source": "0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8",
"target": "58a35684-7d25-4dff-b012-609eab065751",
"animated": false,
"markerEnd": "edge-target",
"markerStart": "edge-source",
"sourceHandle": "condition-true"
},
{
"id": "xy-edge__0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8condition-false-8f6bd336-3d7c-41fe-b94c-d47974c1e056",
"type": "custom-edge",
"style": { "stroke": "#76A9FA", "strokeWidth": 2 },
"source": "0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8",
"target": "8f6bd336-3d7c-41fe-b94c-d47974c1e056",
"animated": false,
"markerEnd": "edge-target",
"markerStart": "edge-source",
"sourceHandle": "condition-false"
}
],
"nodes": [
{
"id": "052af1cb-86fd-443a-bc25-626c365025db",
"type": "trigger-node",
"position": { "x": 250, "y": 0 },
"data": {
"id": "052af1cb-86fd-443a-bc25-626c365025db",
"name": "Trigger",
"label": "Trigger",
"version": "0.1",
"input_fields": [
{
"id": "category",
"title": "Category",
"type": "text",
"input_requirements": true,
"placeholder": "Enter category",
"tooltip": "",
"default_value": "",
"is_secret": false,
"options": []
}
],
"next_nodes": ["0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8"]
}
},
{
"id": "0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8",
"type": "if-else-node",
"position": { "x": 550, "y": 0 },
"data": {
"id": "0a4c9bdb-0378-4426-9e4d-0ba5c6e3e5a8",
"name": "If",
"label": "If",
"version": "0.1",
"condition": {
"left": "{{ input.category }}",
"right": "positive",
"operator": "=="
},
"true_node": "58a35684-7d25-4dff-b012-609eab065751",
"false_node": "8f6bd336-3d7c-41fe-b94c-d47974c1e056",
"next_nodes": [
"58a35684-7d25-4dff-b012-609eab065751",
"8f6bd336-3d7c-41fe-b94c-d47974c1e056"
]
}
},
{
"id": "58a35684-7d25-4dff-b012-609eab065751",
"type": "basic-node",
"position": { "x": 850, "y": -160 },
"data": {
"id": "58a35684-7d25-4dff-b012-609eab065751",
"name": "LLM OpenAI",
"label": "LLMOpenAI",
"version": "0.1",
"messages": [
{
"role": "system",
"message": "You are a helpful assistant. Reply briefly."
},
{
"role": "user",
"message": "The sentiment is positive. Provide a short encouraging response."
}
],
"settings": {
"model_name": "gpt-4o",
"temperature": 0.7
},
"next_nodes": []
}
},
{
"id": "8f6bd336-3d7c-41fe-b94c-d47974c1e056",
"type": "basic-node",
"position": { "x": 850, "y": 136 },
"data": {
"id": "8f6bd336-3d7c-41fe-b94c-d47974c1e056",
"name": "LLM OpenAI",
"label": "LLMOpenAI 1",
"version": "0.1",
"messages": [
{
"role": "system",
"message": "You are a helpful assistant. Reply briefly."
},
{
"role": "user",
"message": "The sentiment is negative. Provide a short empathetic response."
}
],
"settings": {
"model_name": "gpt-4o",
"temperature": 0.7
},
"next_nodes": []
}
}
],
"viewport": { "x": 434, "y": 557, "zoom": 1.0 },
"start_node": "052af1cb-86fd-443a-bc25-626c365025db"
}
}

How to read this example:

  • start_node — UUID of the first node to execute (Trigger).
  • edges — connections between nodes. sourcetarget. For if-else-node, the sourceHandle field indicates which branch (condition-true / condition-false).
  • nodes[].type — frontend node type used for rendering: trigger-node, if-else-node, basic-node, http-node, etc. Note: this is distinct from the node_type field returned by GET /api/v1/workflows/get_nodes/, which uses executor schema class names (e.g. "TriggerNode", "HTTPNodeInput").
  • nodes[].data.input_fields — fields declared in the Trigger node. These map to {{ input.<field_id> }} variables throughout the workflow. A field with is_secret: true holds a credential: the workflow API never returns its value — default_value, and the field's value inside input_data and inside the run result, all come back as ********. Sending ******** back in a PATCH /api/v1/workflows/{id}/ or in a run request keeps the stored value; send a new value to replace it. On create there is nothing to restore, so ******** would be stored literally.
  • nodes[].data.condition — for if-else-node: compares left and right using operator. Supports ==, !=, >, <, >=, <=.
  • nodes[].data.messages — for LLM nodes: the prompt messages array (system + user roles).
  • nodes[].data.next_nodes — list of downstream node UUIDs.

API Endpoints

Every Workflow and WorkflowRun endpoint is listed below. Unless stated otherwise, each one is authenticated with your API key in the X-Api-Key header.

MethodPathDescription
POST/api/v1/workflows/Create a workflow.
GET/api/v1/workflows/List workflows of a project.
GET/api/v1/workflows/{id}/Retrieve a workflow.
PATCH/api/v1/workflows/{id}/Update a workflow.
DELETE/api/v1/workflows/{id}/Delete (archive) a workflow.
POST/api/v1/workflows/{id}/duplicate/Copy a workflow inside the same project.
POST/api/v1/workflows/{id}/reorder/Move a workflow within the project list.
GET/api/v1/workflows/{id}/input-fields/List the input fields declared in the Trigger node.
GET/api/v1/workflows/{id}/check_workflow/Validate the structure of a saved workflow.
GET/api/v1/workflows/get_nodes/List the available node schemas.
POST/api/v1/workflows/mcp-tools/Discover the tools exposed by an MCP server.
POST/api/v1/workflows/{id}/run/Start a workflow run.
GET/api/v1/workflows/workflow_result/Poll the status and result of a run.
GET/api/v1/workflows/{id}/history/List the run history of a workflow.
GET/api/v1/workflows/{id}/history/{run_id}/Retrieve a single run from the history.
POST/api/v1/workflows/{id}/history/{run_id}/re-run/Re-run a previous run.
POST/api/v1/workflows/{id}/history/{run_id}/toggle-api-run/Mark a run as the workflow's API run.
POST/api/v1/workflows/{id}/history/{run_id}/toggle-marketplace-example/Mark a run as a marketplace example.
POST/api/v1/workflows/{id}/history/{run_id}/toggle-marketplace-use/Mark a run as the marketplace template.
GET/api/v1/billing-history/workflowrun/{run_id}/Per-node cost breakdown of a run.
POST/api/v1/workflows/workflow_run/{workflow_run_id}/agent-approval/{request_id}/approve/Approve a pending Agent node request.
POST/api/v1/workflows/workflow_run/{workflow_run_id}/agent-approval/{request_id}/reject/Reject a pending Agent node request.
POST/api/v1/workflows/{id}/publish-on-marketplace/Publish a workflow on the marketplace.
POST/api/v1/workflows/{id}/unpublish-from-marketplace/Remove a workflow from the marketplace.
GET/api/v1/all-workflows/List your workflows across all projects.
GET/api/v1/all-workflows/{id}/Retrieve a workflow from the cross-project list.
POST/api/v1/all-workflows/{id}/add-bookmark/Bookmark a workflow.
DELETE/api/v1/all-workflows/{id}/delete-bookmark/Remove a bookmark from a workflow.
GET/api/v1/workflows/marketplace/List the workflows published on the marketplace.
GET/api/v1/workflows/marketplace/{slug}/Retrieve a marketplace workflow.
POST/api/v1/workflows/marketplace/{slug}/add-from-marketplace/Copy a marketplace workflow into your project.
GET/api/v1/workflows/marketplace/{slug}/examples/List the example runs of a marketplace workflow.
GET/api/v1/workflows/marketplace/{slug}/examples/{run_id}/Retrieve a single example run.
POST/api/v1/workflows/execution-update/{workflow_run_id}/Service-to-service execution webhook. Not callable with an API key.
note

/api/v1/workflows/execution-update/{workflow_run_id}/ is called by the execution service itself and is authenticated with an internal service token. It is listed here for completeness only — client integrations never call it.

Create a Workflow

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/"
headers = {"X-Api-Key": "<Your API Key>"}
data = {
"project": 307,
"title": "New workflow",
"data": {} # see structure above
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{
"project": 307,
"title": "New workflow",
"data": {}
}'

POST /api/v1/workflows/

Summary: Creates a new workflow.

Request Body:

NameTypeRequiredDescription
projectintegerYesProject ID to which the workflow belongs.
titlestringYesName/title of the workflow.
dataobjectYesWorkflow structure (nodes, edges, viewport)

Responses:

  • 201: Workflow successfully created.
  • 400: Invalid input or missing required parameters.

Retrieve Workflows

Python
url = "https://scriptrun.ai/api/v1/workflows/"
headers = {"X-Api-Key": "<Your API Key>"}
params = {"project": 307}

response = requests.get(url, headers=headers, params=params)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/?project=307" \
-H "X-Api-Key: <Your API Key>"

GET /api/v1/workflows/

Summary: Retrieves a list of workflows, optionally filtered by project.

Parameters:

NameInTypeRequiredDescription
projectqueryintegerNoFilter workflows by project ID.
titlequerystringNoFilter by workflow title (case-insensitive).
pagequeryintegerNoPage number for pagination.

Responses:

  • 200: Returns a paginated list of workflows.

Retrieve a Specific Workflow

Python
url = "https://scriptrun.ai/api/v1/workflows/6/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.get(url, headers=headers)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/6/" \
-H "X-Api-Key: <Your API Key>"

GET /api/v1/workflows/{id}/

Summary: Retrieves the details of a specific workflow by its ID.

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow to fetch.

Responses:

  • 200: Returns the workflow details.
  • 404: Workflow not found.

Update a Workflow

Python
url = "https://scriptrun.ai/api/v1/workflows/6/"
headers = {"X-Api-Key": "<Your API Key>"}
data = {
"title": "Updated Workflow Title",
"data": {}
}

response = requests.patch(url, headers=headers, json=data)
print(response.json())
Shell
curl -X PATCH "https://scriptrun.ai/api/v1/workflows/6/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Workflow Title",
"data": {}
}'

PATCH /api/v1/workflows/{id}/

Summary: Updates an existing workflow.

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow to update.

Request Body:

NameTypeRequiredDescription
titlestringNoUpdated workflow title.
dataobjectNoUpdated workflow structure.

Responses:

  • 200: Workflow successfully updated.
  • 404: Workflow not found.

Delete a Workflow

Python
url = "https://scriptrun.ai/api/v1/workflows/6/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.delete(url, headers=headers)
print(response.status_code)
Shell
curl -X DELETE "https://scriptrun.ai/api/v1/workflows/6/" \
-H "X-Api-Key: <Your API Key>"

DELETE /api/v1/workflows/{id}/

Summary: Deletes a specific workflow by its ID.

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow to delete.

Responses:

  • 204: Workflow successfully deleted.
  • 404: Workflow not found.

Additional Workflow Endpoints

Get Workflow Input Fields

GET /api/v1/workflows/{id}/input-fields/

Summary: Returns the list of input fields defined in the workflow's Trigger node. Use this to discover what parameters the workflow expects before running it.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/271/input-fields/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.get(url, headers=headers)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/271/input-fields/" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.

Response (200):

Returns an array of input field objects:

FieldTypeDescription
idstringField identifier (used as key in input data).
titlestringHuman-readable field label.
typestringField type (e.g., text, select, number).
input_requirementsbooleanWhether the field is required.
placeholderstringPlaceholder text for the field.
tooltipstringHelper text shown to the user.
default_valuestringDefault value if none is provided. Returned as ******** when is_secret is true.
is_secretbooleanWhether the field holds a secret (e.g. an access token).
optionsarrayAvailable options for select type fields.

Example Response:

[
{
"id": "user_name",
"title": "User Name",
"type": "text",
"input_requirements": true,
"placeholder": "Enter your name",
"tooltip": "Full name of the user",
"default_value": "",
"is_secret": false,
"options": []
},
{
"id": "language",
"title": "Language",
"type": "select",
"input_requirements": false,
"placeholder": "",
"tooltip": "Output language",
"default_value": "en",
"is_secret": false,
"options": [
{"title": "English", "value": "en", "is_default": true},
{"title": "Russian", "value": "ru", "is_default": false}
]
}
]

Check Workflow Structure

GET /api/v1/workflows/{id}/check_workflow/

Summary: Validates the structure of a saved workflow.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/check_workflow/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.get(url, headers=headers)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/6/check_workflow/" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.

Responses:

  • 200: Validation result returned.
  • 404: Workflow not found.

Get Node Schemas for Frontend

GET /api/v1/workflows/get_nodes/

Summary: Retrieves the available node schemas for rendering and configuration in the frontend.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/get_nodes/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.get(url, headers=headers)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/get_nodes/" \
-H "X-Api-Key: <Your API Key>"

Discover MCP Tools

POST /api/v1/workflows/mcp-tools/

Summary: Connects to an MCP (Model Context Protocol) server and returns the list of tools it exposes. Use this to discover the available tools before configuring an MCP node in a workflow.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/mcp-tools/"
headers = {"X-Api-Key": "<Your API Key>", "Content-Type": "application/json"}
data = {
"endpoint_url": "https://mcp.example.com/sse",
"transport": "auto"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/mcp-tools/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{
"endpoint_url": "https://mcp.example.com/sse",
"transport": "auto"
}'

Request Body:

NameTypeRequiredDescription
endpoint_urlstringYesURL of the MCP server to connect to.
transportstringNoTransport protocol: auto (default), sse, or streamable_http.
headersobjectNoExtra HTTP headers to send to the MCP server (e.g. for authentication).
timeoutnumberNoConnection timeout in seconds (0.130.0, default 10.0).
workflow_idintegerNoExisting workflow to resolve stored MCP configuration from. Must be sent together with node_id.
node_idstringNoNode UUID within workflow_id to resolve stored MCP configuration from.

Responses:

  • 200: Returns the list of tools exposed by the MCP server.
  • 400: Validation error (for example, workflow_id and node_id must be provided together).

Duplicate a Workflow

POST /api/v1/workflows/{id}/duplicate/

Summary: Creates a full copy of a workflow (nodes, edges and settings) inside the same project. The copy is a new, independent workflow with its own ID.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/duplicate/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.post(url, headers=headers)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/duplicate/" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow to copy.

Responses:

  • 201: Returns the newly created workflow.
  • 400: Your project role may not duplicate workflows.
  • 404: Workflow not found.

Reorder a Workflow

POST /api/v1/workflows/{id}/reorder/

Summary: Moves a workflow to a new position in its project's list. The other workflows of the project are shifted accordingly.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/reorder/"
headers = {"X-Api-Key": "<Your API Key>"}
data = {"sort_id": 3}

response = requests.post(url, headers=headers, json=data)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/reorder/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{"sort_id": 3}'

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.

Request Body:

NameTypeRequiredDescription
sort_idintegerYesTarget position of the workflow in the project.

Responses:

  • 200: Returns the workflow with its updated position.
  • 400: sort_id is missing, or your project role may not reorder workflows.
  • 404: Workflow not found.

Publish a Workflow on the Marketplace

POST /api/v1/workflows/{id}/publish-on-marketplace/

Summary: Publishes a workflow on the ScriptRun marketplace so other users can find and copy it.

Before publishing, the workflow must have market_title, short_description and available_languages filled in, and one of its runs must be marked as the marketplace template with POST /api/v1/workflows/{id}/history/{run_id}/toggle-marketplace-use/.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/publish-on-marketplace/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.post(url, headers=headers)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/publish-on-marketplace/" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.

Responses:

  • 200: Returns the published workflow.
  • 400: A required marketplace field is empty, no template run is marked, or your project role may not publish workflows.
  • 404: Workflow not found.

Unpublish a Workflow from the Marketplace

POST /api/v1/workflows/{id}/unpublish-from-marketplace/

Summary: Removes a workflow from the marketplace. Copies already made by other users are not affected.

Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/unpublish-from-marketplace/" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.

Responses:

  • 200: Returns the unpublished workflow.
  • 400: Your project role may not unpublish workflows.
  • 404: Workflow not found.

Running a Workflow

POST /api/v1/workflows/{id}/run/

Summary: Starts the execution of a specific workflow. Optionally pass input data to parameterize the run.


Request Format: Two Modes

The /run/ endpoint behaves differently depending on the authentication method used. Both modes are officially supported. There is no planned deprecation of either format.

Mode 1 — API Key (X-Api-Key header): flat body (canonical for API integrations)

When authenticating with an API key, send the input data directly as the request body — either as a raw JSON string or plain text. Do not wrap in input_data.

This is the recommended format for all API integrations.

Python (API Key — flat body)
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/run/"
headers = {
"X-Api-Key": "<Your API Key>",
"Content-Type": "application/json",
}
# Send input fields directly as JSON body
body = '{"user_name": "John Doe", "email": "[email protected]"}'

response = requests.post(url, headers=headers, data=body)
print(response.json())
Shell (API Key — flat body)
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/run/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{"user_name": "John Doe", "email": "[email protected]"}'

Plain text is also accepted:

Shell (API Key — plain text body)
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/run/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: text/plain" \
-d "Hello, process this text"

Mode 2 — JWT (frontend / session): input_data wrapper

When authenticating with JWT (frontend sessions), wrap the input inside input_data:

Python (JWT — input_data wrapper)
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/run/"
headers = {"Authorization": "Bearer <JWT Token>"}
data = {
"input_data": {
"user_name": "John Doe",
"email": "[email protected]"
}
}

response = requests.post(url, headers=headers, json=data)
print(response.json())

Summary of request format by auth mode:

Auth methodRequest body formatContent-Type
X-Api-Key headerRaw JSON string or plain text (flat)application/json or text/plain
JWT Bearer token{"input_data": { ... }}application/json

Parameters

NameInTypeRequiredDescription
idpathintegerYesID of the workflow to run.

Response (200)

The endpoint returns HTTP 200 with a JSON body in the following format:

{
"data": {
"id": "0781b175-2135-45ec-9063-ad3e0d929adc",
"status": "in queue",
"data": null
},
"status": 201
}
FieldTypeDescription
statusintegerHTTP status code returned by the execution service. 201 = accepted and started.
dataobjectExecution service response body.
data.idstring (UUID)WorkflowRun identifier. Save it — use for polling via GET /workflow_result/?id=<uuid>.
data.statusstringInitial run status. Always "in queue" for a freshly accepted run.
data.datanullAlways null in the /run/ response. Result data is fetched via GET /workflow_result/.
important

data.id is a UUID string (e.g., "0781b175-2135-45ec-9063-ad3e0d929adc"), not an integer. Do not compare with workflow IDs.

Error response (node validation failure):

When a node in the workflow fails validation (e.g. missing required field), the endpoint returns HTTP 200 with inner status: 422 and a per-node error structure:

{
"data": {
"id": "0781b175-2135-45ec-9063-ad3e0d929adc",
"status": "failed",
"data": {
"9919a3fd-7e59-439c-b918-3ee5977654b5": {
"id": "9919a3fd-7e59-439c-b918-3ee5977654b5",
"status": "failed",
"result": [
{"messages.0.message": "String should have at least 1 character"}
]
}
}
},
"status": 422
}

Check response["status"] (not HTTP status) to distinguish success from error:

  • status == 201 — workflow run was accepted and is executing
  • status == 422 — node validation error, run was not started (data.data contains per-node errors)
  • status == 400 — structural error (malformed workflow JSON)

Polling pattern

Python — full run + poll
import time
import requests

API_KEY = "<Your API Key>"
WORKFLOW_ID = 6

# 1. Start the run
run_resp = requests.post(
f"https://scriptrun.ai/api/v1/workflows/{WORKFLOW_ID}/run/",
headers={"X-Api-Key": API_KEY, "Content-Type": "application/json"},
data='{"user_name": "John Doe"}',
)
run_body = run_resp.json()

if run_body.get("status") != 201:
raise RuntimeError(f"Workflow failed to start: {run_body}")

run_id = run_body["data"]["id"] # UUID string

# 2. Poll until complete
TERMINAL_STATUSES = {"succeed", "failed"}
for _ in range(60):
result_resp = requests.get(
"https://scriptrun.ai/api/v1/workflows/workflow_result/",
headers={"X-Api-Key": API_KEY},
params={"id": run_id},
)
result = result_resp.json()
executor_data = result.get("data", {})
current_status = executor_data.get("status")

if current_status in TERMINAL_STATUSES:
print("Done:", executor_data)
break

time.sleep(3)
else:
print("Timed out")

Get Workflow Run Result

GET /api/v1/workflows/workflow_result/

Summary: Retrieves the current status and result of a workflow run by its UUID. Use this endpoint for polling after calling /run/.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/workflow_result/"
headers = {"X-Api-Key": "<Your API Key>"}
params = {"id": "0781b175-2135-45ec-9063-ad3e0d929adc"}

response = requests.get(url, headers=headers, params=params)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/workflow_result/?id=0781b175-2135-45ec-9063-ad3e0d929adc" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idquerystringYesUUID of the workflow run (from /run/ response data.id).

Full Response Schema

The endpoint returns HTTP 200 with the following structure:

{
"data": {
"id": "0781b175-2135-45ec-9063-ad3e0d929adc",
"status": "succeed",
"data": {
"93e9822b-63a4-4553-adb4-79029db3c09b": {
"id": "93e9822b-63a4-4553-adb4-79029db3c09b",
"status": "succeed",
"result": {
"content": "Hi! How can I help you today?"
}
},
"a7bf1234-0000-0000-0000-000000000001": {
"id": "a7bf1234-0000-0000-0000-000000000001",
"status": "succeed",
"result": {
"content": "{\"key\": \"value\"}"
}
}
}
},
"status": 200
}

Top-level fields:

FieldTypeDescription
statusintegerHTTP status from executor. 200 = response delivered.
dataobjectExecutor response body. See nested fields below.

data object fields:

FieldTypeDescription
idstringUUID of the workflow run (same as the query parameter).
statusstringOverall run status. See allowed values below.
dataobjectPer-node results, keyed by node UUID (not node name).

Allowed status Values

ValueMeaning
"in queue"Run is queued, execution has not started yet.
"in progress"Execution is active.
"succeed"Execution completed successfully. Results are ready.
"failed"Execution completed with an error.
"not found"No run found for this UUID. May be expired or invalid.

Terminal statuses (stop polling): "succeed", "failed".

Non-terminal statuses (continue polling): "in queue", "in progress".


Per-Node Result Object (data.data.<node-uuid>)

Each node UUID maps to:

FieldTypeDescription
idstringNode UUID (same as the key).
statusstringNode-level status. Same values as run-level status.
resultobjectNode output. Present only when node status is succeed.

result object:

FieldTypeDescription
contentstringNode output content. See result.content formats below.

Node Order

data.data is a JSON object keyed by node UUID, not an array. Node order is not guaranteed — do not rely on insertion order. To identify specific nodes, use their UUID (obtainable from GET /api/v1/workflows/{id}/data.nodes[].id).


Determining the Final Result

Check that overall data.status == "succeed" before reading results. Only then are node results in data.data final.

Do not assume the last key in data.data is the output — iteration order is not stable. Use node UUIDs from the workflow definition (GET /api/v1/workflows/{id}/) to identify specific nodes.


Error Responses

HTTP StatusMeaning
400Missing id parameter, or run not found in database / no access.
401Authentication credentials not provided.
note

If the run exists in the database but the executor has no result for it (expired or not yet persisted), the endpoint returns HTTP 200 with data.status: "not found" and data.data: null — not an HTTP error. Treat "not found" as a non-terminal status and retry after a short delay.


result.content Formats

The result.content field is always a string, but its semantic content varies:

FormatExampleHow to handle
Plain text"Hello, world!"Use directly.
JSON string"{\"key\": \"value\"}"Parse with json.loads().
Markdown JSON code fence```json\n{"key": "value"}\n```Strip the fence, then parse JSON.
Python — robust content parser
import json
import re

def parse_content(content: str):
"""Parse result.content regardless of format."""
# Strip markdown code fence if present
fence_match = re.match(r"```(?:json)?\s*([\s\S]*?)\s*```", content.strip())
if fence_match:
content = fence_match.group(1)

try:
return json.loads(content)
except (json.JSONDecodeError, ValueError):
return content # plain text
note

The markdown code fence wrapping (```json ... ```) is a known quirk produced by certain LLM nodes. The API does not currently normalize this on the server side. Use the parser above on the client side.


Workflow Run History

GET /api/v1/workflows/{id}/history/

Summary: Retrieves the paginated run history for a specific workflow.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/history/"
headers = {"X-Api-Key": "<Your API Key>"}
params = {"size": 10, "ordering": "-created_at"}

response = requests.get(url, headers=headers, params=params)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/6/history/?size=10&ordering=-created_at" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.
orderingquerystringNoSort field. Options: created_at, -created_at, cost, -cost.
pagequeryintegerNoPage number.
sizequeryintegerNoNumber of items per page.

Responses:

  • 200: Returns a paginated list of workflow run history items.
  • 404: Workflow not found.

History item fields:

FieldTypeDescription
idstringUUID of the run.
created_atstringWhen the run was created.
updated_atstringWhen the run was last updated.
run_started_atstringWhen execution started (null while queued).
run_finished_atstringWhen execution finished (null while running).
statusstringRun status label (e.g. Succeeded, Error).
resultobjectResult payload of the run.
dataobjectWorkflow structure the run was executed with.
input_dataobjectInput data the run was started with.
input_fieldsarrayTrigger input fields of that run, same shape as input-fields.
is_api_runbooleanWhether this run is the workflow's API run.
use_in_marketplace_examplebooleanWhether this run is shown as a marketplace example.
use_as_marketplace_templatebooleanWhether this run is the marketplace template.
costobjectRun cost, converted to the available currencies.
durationnumberRun duration in seconds (null if it never finished).
note

status here is the stored run status — In Progress, Succeeded, Cancelled, Error or Draft. These are not the execution-service statuses (in queue, in progress, succeed, failed) returned by GET /workflow_result/.

Retrieve a Single Run

GET /api/v1/workflows/{id}/history/{run_id}/

Summary: Retrieves one run of a workflow, with the same fields as a history list item.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/history/d2d20381-85c5-4a2d-8680-a2134dc8854f/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.get(url, headers=headers)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/6/history/d2d20381-85c5-4a2d-8680-a2134dc8854f/" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.
run_idpathstringYesUUID of the workflow run.

Responses:

  • 200: Returns the run.
  • 404: Workflow or run not found.

Re-run a Workflow

POST /api/v1/workflows/{id}/history/{run_id}/re-run/

Summary: Creates and starts a new workflow run based on a previous run. Useful for retrying failed runs or re-executing with the same or updated input data.

Python (API Key — re-run with new input)
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/history/11122222-4444-4444-8888-a2134dc8854f/re-run/"
headers = {
"X-Api-Key": "<Your API Key>",
"Content-Type": "application/json",
}
# Optionally provide new input data; omit body to reuse the original input
body = '{"user_name": "Jane Doe"}'

response = requests.post(url, headers=headers, data=body)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/history/d2d20381-85c5-4a2d-8680-a2134dc8854f/re-run/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{"user_name": "Jane Doe"}'

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.
run_idpathstringYesUUID of the existing workflow run.

Request body: Same format as POST /run/ — flat JSON body (API key) or {"input_data": {...}} (JWT). If omitted, the original run's input is used.

Response (201):

Same structure as POST /run/:

{
"data": {
"id": "new-run-uuid-here",
"status": "in queue",
"data": null
},
"status": 201
}

Use data.id to poll for results via GET /workflow_result/.

Responses:

  • 201: New workflow run created and submitted.
  • 400: Validation error.
  • 404: Workflow or original run not found.

Mark a Run as the API Run

POST /api/v1/workflows/{id}/history/{run_id}/toggle-api-run/

Summary: Marks a run as the workflow's API run — the run whose configuration is used when the workflow is started through the API. A workflow has at most one API run: marking a new one automatically clears the flag on the previous run.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/history/d2d20381-85c5-4a2d-8680-a2134dc8854f/toggle-api-run/"
headers = {"X-Api-Key": "<Your API Key>"}
data = {"is_api_run": True}

response = requests.post(url, headers=headers, json=data)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/history/d2d20381-85c5-4a2d-8680-a2134dc8854f/toggle-api-run/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{"is_api_run": true}'

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.
run_idpathstringYesUUID of the workflow run.

Request Body:

NameTypeRequiredDescription
is_api_runbooleanYesNew value of the is_api_run flag.

Responses:

  • 200: Returns the updated run.
  • 400: Validation error, or your project role may not modify the flag.
  • 404: Workflow or run not found.

Mark a Run as a Marketplace Example

POST /api/v1/workflows/{id}/history/{run_id}/toggle-marketplace-example/

Summary: Marks a run as an example shown on the workflow's marketplace page. A workflow may have several example runs.

Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/history/d2d20381-85c5-4a2d-8680-a2134dc8854f/toggle-marketplace-example/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{"use_in_marketplace_example": true}'

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.
run_idpathstringYesUUID of the workflow run.

Request Body:

NameTypeRequiredDescription
use_in_marketplace_examplebooleanYesNew value of the use_in_marketplace_example flag.

Responses:

  • 200: Returns the updated run.
  • 400: Validation error, or your project role may not change this flag — only project owners and admins can.
  • 404: Workflow or run not found.

Mark a Run as the Marketplace Template

POST /api/v1/workflows/{id}/history/{run_id}/toggle-marketplace-use/

Summary: Marks a run as the marketplace template — the run that is copied when another user adds the workflow from the marketplace. A workflow must have a template run before it can be published.

Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/history/d2d20381-85c5-4a2d-8680-a2134dc8854f/toggle-marketplace-use/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{"use_as_marketplace_template": true}'

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.
run_idpathstringYesUUID of the workflow run.

Request Body:

NameTypeRequiredDescription
use_as_marketplace_templatebooleanYesNew value of the use_as_marketplace_template flag.

Responses:

  • 200: Returns the updated run.
  • 400: Validation error; only project owners and admins may set this flag, the run must have completed successfully, and it must carry workflow data.
  • 404: Workflow or run not found.

Per-node Cost of a Run

GET /api/v1/billing-history/workflowrun/{run_id}/

Summary: Returns the billing transactions of a single workflow run — one per executed node — so you can see what each step of the run cost.

Python
import requests

url = "https://scriptrun.ai/api/v1/billing-history/workflowrun/0781b175-2135-45ec-9063-ad3e0d929adc/"
headers = {"X-Api-Key": "<Your API Key>"}
params = {"page": 1, "size": 10}

response = requests.get(url, headers=headers, params=params)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/billing-history/workflowrun/0781b175-2135-45ec-9063-ad3e0d929adc/?page=1&size=10" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
run_idpathstringYesUUID of the workflow run.
pagequeryintegerNoPage number, starting at 1. Defaults to 1.
sizequeryintegerNoItems per page (1–100). Defaults to 10.

Response (200): a paginated envelope — items, page, size, total — where each item is:

FieldTypeDescription
idstringTransaction identifier.
operationstringTransaction type.
statusstringStatus of the node charge. Failed nodes are reported as Error.
amountobjectCharged amount, converted to the available currencies.
reasonstringReason recorded for the transaction.
descriptionstringLabel of the node the charge belongs to.
run_idstringUUID of the workflow run.
user_idintegerID of the charged user.
created_atstringWhen the transaction was created.
updated_atstringWhen the transaction was last updated.

Responses:

  • 200: Returns the paginated node transactions of the run.
  • 400: Invalid pagination parameters.

Agent Node Approvals

Agent nodes can be configured to pause and wait for a human decision before they perform an action. While a run is waiting, the executor exposes an approval request that you resolve with one of the two endpoints below. Both take the UUID of the workflow run and the ID of the pending approval request, and both return the executor's response.

Approve an Agent Request

POST /api/v1/workflows/workflow_run/{workflow_run_id}/agent-approval/{request_id}/approve/

Summary: Approves a pending Agent node request so the run continues.

Python
import requests

run_id = "0781b175-2135-45ec-9063-ad3e0d929adc"
request_id = "b41f0b32-1f2f-4a1a-9d10-5f7c9a2f0f77"
url = (
f"https://scriptrun.ai/api/v1/workflows/workflow_run/{run_id}"
f"/agent-approval/{request_id}/approve/"
)
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.post(url, headers=headers)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/workflow_run/0781b175-2135-45ec-9063-ad3e0d929adc/agent-approval/b41f0b32-1f2f-4a1a-9d10-5f7c9a2f0f77/approve/" \
-H "X-Api-Key: <Your API Key>"

Reject an Agent Request

POST /api/v1/workflows/workflow_run/{workflow_run_id}/agent-approval/{request_id}/reject/

Summary: Rejects a pending Agent node request.

Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/workflow_run/0781b175-2135-45ec-9063-ad3e0d929adc/agent-approval/b41f0b32-1f2f-4a1a-9d10-5f7c9a2f0f77/reject/" \
-H "X-Api-Key: <Your API Key>"

Parameters (both endpoints):

NameInTypeRequiredDescription
workflow_run_idpathstringYesUUID of the workflow run that is waiting.
request_idpathstringYesIdentifier of the pending approval request.

Responses:

  • 200: Returns the executor response for the resolved request.
  • 404: The run does not exist, or you have no access to its project.

Temporal Semantics: Polling After Status Update

Critical for client implementations

There is a known timing window between when the execution service marks a run as complete and when GET /workflow_result/ returns fully consistent data.

What this means:

  • The run status may transition to "succeed" or "failed" in the backend database slightly before the result data is fully persisted.
  • If you poll workflow_result immediately after detecting a "succeed" status, data.data may be partially populated or empty.

Recommended retry strategy:

  1. Poll workflow_result every 3–5 seconds while status is non-terminal.
  2. When status becomes "succeed" or "failed", verify that data.data is non-empty and contains the expected output nodes.
  3. If data.data is empty or missing expected nodes despite a terminal status, wait 2–3 seconds and retry (up to 3 retries).
  4. Only finalize your result after both conditions are true: terminal status AND non-empty data.data.
Python — robust polling with consistency check
import time
import requests

def poll_workflow_result(run_id: str, api_key: str, timeout_seconds: int = 180):
headers = {"X-Api-Key": api_key}
url = "https://scriptrun.ai/api/v1/workflows/workflow_result/"
terminal = {"succeed", "failed"}
deadline = time.time() + timeout_seconds

while time.time() < deadline:
resp = requests.get(url, headers=headers, params={"id": run_id})
body = resp.json()
data = body.get("data", {})
status = data.get("status")

if status in terminal:
node_results = data.get("data", {})
if node_results:
return data # fully consistent result
# Terminal but data not yet available — brief consistency window
time.sleep(2)
continue

time.sleep(3)

raise TimeoutError(f"Workflow run {run_id} did not complete within {timeout_seconds}s")

Workflow Catalog and Bookmarks

/api/v1/workflows/ is scoped to a single project. /api/v1/all-workflows/ returns your workflows across all projects you are a member of, with the aggregated run metrics used by the workflow catalog, and lets you bookmark them. Bookmarked workflows are returned first.

List Workflows Across Projects

GET /api/v1/all-workflows/

Summary: Lists your workflows across all projects.

Python
import requests

url = "https://scriptrun.ai/api/v1/all-workflows/"
headers = {"X-Api-Key": "<Your API Key>"}
params = {"search": "classification", "ordering": "-last_run_at"}

response = requests.get(url, headers=headers, params=params)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/all-workflows/?search=classification&ordering=-last_run_at" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
searchquerystringNoCase-insensitive match on the workflow title or marketplace title.
title__icontainsquerystringNoCase-insensitive match on the workflow title.
projectqueryintegerNoFilter by project ID.
categoriesqueryintegerNoFilter by category ID. Repeat the parameter for several categories.
subcategoriesqueryintegerNoFilter by subcategory ID. Repeat the parameter for several subcategories.
languagesquerystringNoComma-separated language codes; matches workflows available in any of them.
own_scriptsquerybooleanNoOnly workflows you authored. Defaults to false.
orderingquerystringNoSort field: last_run_at, total_cost, created_at, each also with a - prefix. Bookmarked workflows stay on top.
pagequeryintegerNoPage number.
sizequeryintegerNoNumber of items per page.

Responses:

  • 200: Returns a paginated list of workflows, including is_bookmarked, last_run_at, last_run_cost, average_run_duration and total_cost.

Retrieve a Workflow from the Catalog

GET /api/v1/all-workflows/{id}/

Summary: Retrieves one workflow from the cross-project list, with the same detailed fields.

Shell
curl -X GET "https://scriptrun.ai/api/v1/all-workflows/6/" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
idpathintegerYesID of the workflow.

Responses:

  • 200: Returns the workflow.
  • 404: Workflow not found.

Bookmark a Workflow

POST /api/v1/all-workflows/{id}/add-bookmark/

Summary: Bookmarks a workflow for the current user. Bookmarking an already bookmarked workflow is a no-op and still returns 201.

Shell
curl -X POST "https://scriptrun.ai/api/v1/all-workflows/6/add-bookmark/" \
-H "X-Api-Key: <Your API Key>"

Responses:

  • 201: {"message": "Bookmark added"}.
  • 404: Workflow not found.

Remove a Bookmark

DELETE /api/v1/all-workflows/{id}/delete-bookmark/

Summary: Removes the current user's bookmark from a workflow.

Shell
curl -X DELETE "https://scriptrun.ai/api/v1/all-workflows/6/delete-bookmark/" \
-H "X-Api-Key: <Your API Key>"

Responses:

  • 204: Bookmark removed.
  • 404: Workflow not found.

Marketplace Workflows

The marketplace lists workflows their authors published for everyone. Marketplace endpoints are addressed by slug, not by numeric ID, and reading them does not require authentication. Copying a workflow into your own project does.

List Marketplace Workflows

GET /api/v1/workflows/marketplace/

Summary: Lists the published marketplace workflows.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/marketplace/"
params = {"search": "seo", "ordering": "-last_run_at"}

response = requests.get(url, params=params)
print(response.json())
Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/marketplace/?search=seo&ordering=-last_run_at"

Parameters:

NameInTypeRequiredDescription
searchquerystringNoCase-insensitive match on the marketplace title.
categoriesqueryintegerNoFilter by category ID. Repeat the parameter for several categories.
subcategoriesqueryintegerNoFilter by subcategory ID. Repeat for several subcategories.
languagesquerystringNoComma-separated language codes.
marketplace_date_last_publication_afterquerystringNoOnly workflows published on or after this date (YYYY-MM-DD).
marketplace_date_last_publication_beforequerystringNoOnly workflows published on or before this date (YYYY-MM-DD).
orderingquerystringNoSort field: total_cost (average marketplace price), last_run_at, created_at, each also with a - prefix.
pagequeryintegerNoPage number.
sizequeryintegerNoNumber of items per page.

Responses:

  • 200: Returns a paginated list of marketplace workflows.

Marketplace workflow fields (most relevant ones):

FieldTypeDescription
idintegerID of the source workflow.
slugstringMarketplace identifier used in the URLs of these endpoints.
market_titlestringTitle shown on the marketplace.
short_descriptionstringShort marketplace description.
readme_guidestringLong-form usage guide.
available_languagesarrayLanguage codes the workflow is offered in.
run_feestringFee charged per run.
free_runs_per_userintegerNumber of free runs granted to each user.
marketplace_price_avgobjectAverage run price, converted to the available currencies.
copied_workflow_idintegerID of your copy of this workflow, or -1 if you have not copied it.
total_users_countintegerNumber of users who copied the workflow.
total_runs_countintegerTotal number of runs.
last_run_atstringWhen the workflow was last run.

Retrieve a Marketplace Workflow

GET /api/v1/workflows/marketplace/{slug}/

Summary: Retrieves a single marketplace workflow.

Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/"

Parameters:

NameInTypeRequiredDescription
slugpathstringYesMarketplace slug of the workflow.

Responses:

  • 200: Returns the marketplace workflow.
  • 404: No published workflow with this slug.

Copy a Marketplace Workflow

POST /api/v1/workflows/marketplace/{slug}/add-from-marketplace/

Summary: Copies a marketplace workflow into your own project so you can run and edit it. If you are the author of the workflow, the original is returned instead of a copy.

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/add-from-marketplace/"
headers = {"X-Api-Key": "<Your API Key>"}

response = requests.post(url, headers=headers)
print(response.json()["id"]) # ID of your copy
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/add-from-marketplace/" \
-H "X-Api-Key: <Your API Key>"

Parameters:

NameInTypeRequiredDescription
slugpathstringYesMarketplace slug of the workflow.

Responses:

  • 201: Returns your copy of the workflow. Use its id with the regular workflow endpoints.
  • 404: No published workflow with this slug.

Always send your API key with this request: the copy is created for the calling user, so an unauthenticated request cannot succeed.

List Example Runs

GET /api/v1/workflows/marketplace/{slug}/examples/

Summary: Lists the runs the author marked as examples for this marketplace workflow, so you can see the input and the result before copying it.

Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/examples/"

Response (200): an array of example runs.

FieldTypeDescription
idstringUUID of the example run.
created_atstringWhen the run was created.
costobjectRun cost, converted to available currencies.
resultobjectResult payload of the run.
input_dataobjectInput the run was started with.
dataobjectWorkflow structure the run was executed with.

Retrieve an Example Run

GET /api/v1/workflows/marketplace/{slug}/examples/{run_id}/

Summary: Retrieves a single example run of a marketplace workflow.

Shell
curl -X GET "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/examples/0781b175-2135-45ec-9063-ad3e0d929adc/"

Parameters:

NameInTypeRequiredDescription
slugpathstringYesMarketplace slug of the workflow.
run_idpathstringYesUUID of the example run.

Responses:

  • 200: Returns the example run.
  • 404: The run does not exist or is not marked as an example.

Workflow Data Structure

  • nodes: List of nodes, each containing:
    • id: Unique node UUID string (e.g. "3d63f846-0f6a-478c-b91c-5921259429c1").
    • type: Frontend node type (e.g., "trigger-node", "basic-node", "if-else-node", "http-node"). These are UI rendering types — not the same as the executor schema names ("TriggerNode", "HTTPNodeInput", etc.) returned by GET /api/v1/workflows/get_nodes/.
    • data: Node parameters (name, settings, schema, messages, etc.).
    • position, measured, selected, etc. — visualization parameters.
  • edges: List of connections between nodes, each containing:
    • id: Unique edge identifier.
    • source: Source node UUID.
    • target: Target node UUID.
    • type, style, markerEnd, markerStart, etc. — visualization parameters.
  • viewport: Viewport parameters (x, y, zoom).
  • start_node: UUID of the start node (usually the first action or trigger).

Summary

  • A Workflow is a visual process schema consisting of nodes and edges.
  • The API allows you to create, retrieve, update, and delete workflows, as well as duplicate and reorder them.
  • Use GET /api/v1/workflows/{id}/input-fields/ to discover what inputs a workflow expects.
  • Use POST /api/v1/workflows/{id}/run/ to execute a workflow. Save response["data"]["id"] — this is the UUID for polling.
  • Use GET /api/v1/workflows/workflow_result/?id=<run_uuid> to poll for results. Poll until data.status is "succeed" or "failed".
  • Use GET /api/v1/workflows/{id}/history/ to view past runs, and GET /api/v1/workflows/{id}/history/{run_id}/ for a single one.
  • Use the toggle-api-run, toggle-marketplace-example and toggle-marketplace-use endpoints to flag a run for API use, as an example, or as the marketplace template.
  • Use /api/v1/all-workflows/ to browse and bookmark your workflows across all projects.
  • Use /api/v1/workflows/marketplace/ to browse published workflows and copy one into your project.

Working with Input Data

Overview

When running a workflow via API key, send input data directly in the request body (flat format). Access it in nodes using {{ input.* }} variables.

Key Features:

  • ✅ Supports valid JSON objects (flat or nested)
  • ✅ Supports JSON arrays
  • ✅ Supports plain text (automatically wrapped)
  • ✅ Access data in nodes using {{ input.field_name }} syntax
  • ✅ Supports nested objects and arrays

Example 1: Object Input Data

Python
import requests

url = "https://scriptrun.ai/api/v1/workflows/6/run/"
headers = {"X-Api-Key": "<Your API Key>", "Content-Type": "application/json"}

import json
body = json.dumps({
"user_name": "John Doe",
"email": "[email protected]",
"age": 30,
"preferences": {
"theme": "dark",
"notifications": True
},
"tags": ["admin", "developer"]
})

response = requests.post(url, headers=headers, data=body)
print(response.json())
Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/run/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{
"user_name": "John Doe",
"email": "[email protected]",
"age": 30,
"preferences": {
"theme": "dark",
"notifications": true
},
"tags": ["admin", "developer"]
}'

Accessing in nodes:

{{ input.user_name }}              → "John Doe"
{{ input.email }} → "[email protected]"
{{ input.age }} → 30
{{ input.preferences.theme }} → "dark"
{{ input.tags[0] }} → "admin"
{{ input.tags[1] }} → "developer"

Example 2: Array Input Data

Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/run/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: application/json" \
-d '{
"data": [
{"id": 1, "name": "Alice", "role": "admin"},
{"id": 2, "name": "Bob", "role": "user"}
]
}'

Accessing in nodes:

{{ input.data[0].name }}     → "Alice"
{{ input.data[1].role }} → "user"
{{ input.data[0].id }} → 1

Example 3: Plain Text Input

Shell
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/run/" \
-H "X-Api-Key: <Your API Key>" \
-H "Content-Type: text/plain" \
-d "Hello, this is a simple text input"

Accessing in nodes:

{{ input.__raw_input__ }}    → "Hello, this is a simple text input"

Plain text input is automatically wrapped as {"__raw_input__": "..."}. Access via {{ input.__raw_input__ }}.

Adding Variables in the Interface

To add a variable in the workflow node editor in the ScriptRun interface, use double curly braces {{ }}:

Input data variables (values passed when running the workflow via API):

{{ input.field_name }}
{{ input.nested.field }}
{{ input.array[0].field }}
{{ input.__raw_input__ }}

Node output variables (results from other nodes):

Each node has a UUID (visible in the workflow data.nodes[].id). Reference another node's output using:

{{ nodeId.result.content }}

Where nodeId is the UUID of the upstream node. For example:

{{ 93e9822b-63a4-4553-adb4-79029db3c09b.result.content }}

Structure of node output variables:

When the input for a node comes from another node via the API (e.g., when building dynamic chains), the output data from each node is available at:

{{ <nodeId>.result.content }}      → string output of that node
{{ <nodeId>.result.<field> }} → other fields in the node result

This is the same structure that appears in workflow_result response under data.data.<nodeId>.result.

Using Input Data in Nodes

In HTTP Node

{
"url": "https://api.example.com/users",
"method": "POST",
"headers": {
"Authorization": "Bearer {{ input.api_token }}",
"Content-Type": "application/json"
},
"body": {
"name": "{{ input.user_name }}",
"email": "{{ input.email }}",
"age": "{{ input.age }}"
}
}

In LLM Node

{
"messages": [
{
"role": "system",
"message": "You are a helpful assistant"
},
{
"role": "user",
"message": "Create a welcome message for {{ input.user_name }} with email {{ input.email }}"
}
]
}

Complex Example: Nested Structures

Python
import json
import requests

body = json.dumps({
"company": {
"name": "Acme Inc",
"departments": [
{
"name": "IT",
"employees": [
{"name": "Alice", "role": "Developer"},
{"name": "Bob", "role": "DevOps"}
]
},
{
"name": "HR",
"employees": [
{"name": "Charlie", "role": "Manager"}
]
}
]
}
})

response = requests.post(
"https://scriptrun.ai/api/v1/workflows/6/run/",
headers={"X-Api-Key": "<Your API Key>", "Content-Type": "application/json"},
data=body,
)

Accessing nested data in nodes:

{{ input.company.name }}                             → "Acme Inc"
{{ input.company.departments[0].name }} → "IT"
{{ input.company.departments[0].employees[0].name }} → "Alice"
{{ input.company.departments[0].employees[1].role }} → "DevOps"
{{ input.company.departments[1].employees[0].name }} → "Charlie"

Variable Syntax

ScriptRun supports flexible variable syntax for accessing input data:

SyntaxDescriptionExample
{{ input.field }}Access object field{{ input.user_name }}
{{ input.nested.field }}Access nested field{{ input.preferences.theme }}
{{ input[0] }}Access array element by index{{ input[0] }}
{{ input.users[0].name }}Access field in array element{{ input.users[0].name }}
{{ input.tags[1] }}Access nested array element{{ input.tags[1] }}
{{ nodeId.result.content }}Access another node's output{{ 93e9822b-....result.content }}

Both array notations are equivalent:

  • Dot notation: {{ input.tags.0 }}
  • Bracket notation: {{ input.tags[0] }}

Error Handling

Invalid JSON (API key mode):

  • Plain text or invalid JSON is automatically wrapped in {"__raw_input__": "text"}
  • Access it via {{ input.__raw_input__ }}

Missing Fields:

  • If a field doesn't exist, it returns an empty value
  • Example: {{ input.nonexistent_field }}{}

Empty Input:

  • If no input is provided, it defaults to {}

Best Practices

  1. Use descriptive field names: user_name instead of n
  2. Validate required fields: Use Trigger node with required input fields
  3. Keep structure consistent: Use the same data structure for similar workflows
  4. Test with sample data: Verify your variables work before running in production
  5. Handle result.content defensively: Always parse it — it may be plain text, JSON, or markdown-wrapped JSON (see result.content formats)
  6. Implement retry with backoff: When polling, use 3–5 second intervals and handle the brief consistency window after terminal status

Responses

  • 200: Workflow execution started successfully (check inner status field)
  • 400: Invalid input data or workflow structure
  • 404: Workflow not found