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.source→target. Forif-else-node, thesourceHandlefield 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 thenode_typefield returned byGET /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 withis_secret: trueholds a credential: the workflow API never returns its value —default_value, and the field's value insideinput_dataand inside the runresult, all come back as********. Sending********back in aPATCH /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— forif-else-node: comparesleftandrightusingoperator. 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.
| Method | Path | Description |
|---|---|---|
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. |
/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
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())
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:
| Name | Type | Required | Description |
|---|---|---|---|
project | integer | Yes | Project ID to which the workflow belongs. |
title | string | Yes | Name/title of the workflow. |
data | object | Yes | Workflow structure (nodes, edges, viewport) |
Responses:
- 201: Workflow successfully created.
- 400: Invalid input or missing required parameters.
Retrieve Workflows
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())
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
project | query | integer | No | Filter workflows by project ID. |
title | query | string | No | Filter by workflow title (case-insensitive). |
page | query | integer | No | Page number for pagination. |
Responses:
- 200: Returns a paginated list of workflows.
Retrieve a Specific Workflow
url = "https://scriptrun.ai/api/v1/workflows/6/"
headers = {"X-Api-Key": "<Your API Key>"}
response = requests.get(url, headers=headers)
print(response.json())
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow to fetch. |
Responses:
- 200: Returns the workflow details.
- 404: Workflow not found.
Update a Workflow
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())
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow to update. |
Request Body:
| Name | Type | Required | Description |
|---|---|---|---|
title | string | No | Updated workflow title. |
data | object | No | Updated workflow structure. |
Responses:
- 200: Workflow successfully updated.
- 404: Workflow not found.
Delete a Workflow
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)
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID 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.
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())
curl -X GET "https://scriptrun.ai/api/v1/workflows/271/input-fields/" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow. |
Response (200):
Returns an array of input field objects:
| Field | Type | Description |
|---|---|---|
id | string | Field identifier (used as key in input data). |
title | string | Human-readable field label. |
type | string | Field type (e.g., text, select, number). |
input_requirements | boolean | Whether the field is required. |
placeholder | string | Placeholder text for the field. |
tooltip | string | Helper text shown to the user. |
default_value | string | Default value if none is provided. Returned as ******** when is_secret is true. |
is_secret | boolean | Whether the field holds a secret (e.g. an access token). |
options | array | Available 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.
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())
curl -X GET "https://scriptrun.ai/api/v1/workflows/6/check_workflow/" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID 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.
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())
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.
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())
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:
| Name | Type | Required | Description |
|---|---|---|---|
endpoint_url | string | Yes | URL of the MCP server to connect to. |
transport | string | No | Transport protocol: auto (default), sse, or streamable_http. |
headers | object | No | Extra HTTP headers to send to the MCP server (e.g. for authentication). |
timeout | number | No | Connection timeout in seconds (0.1–30.0, default 10.0). |
workflow_id | integer | No | Existing workflow to resolve stored MCP configuration from. Must be sent together with node_id. |
node_id | string | No | Node 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_idandnode_idmust 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.
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())
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/duplicate/" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID 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.
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())
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow. |
Request Body:
| Name | Type | Required | Description |
|---|---|---|---|
sort_id | integer | Yes | Target position of the workflow in the project. |
Responses:
- 200: Returns the workflow with its updated position.
- 400:
sort_idis 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/.
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())
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/publish-on-marketplace/" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID 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.
curl -X POST "https://scriptrun.ai/api/v1/workflows/6/unpublish-from-marketplace/" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID 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.
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())
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:
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:
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 method | Request body format | Content-Type |
|---|---|---|
X-Api-Key header | Raw JSON string or plain text (flat) | application/json or text/plain |
| JWT Bearer token | {"input_data": { ... }} | application/json |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID 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
}
| Field | Type | Description |
|---|---|---|
status | integer | HTTP status code returned by the execution service. 201 = accepted and started. |
data | object | Execution service response body. |
data.id | string (UUID) | WorkflowRun identifier. Save it — use for polling via GET /workflow_result/?id=<uuid>. |
data.status | string | Initial run status. Always "in queue" for a freshly accepted run. |
data.data | null | Always null in the /run/ response. Result data is fetched via GET /workflow_result/. |
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 executingstatus == 422— node validation error, run was not started (data.datacontains per-node errors)status == 400— structural error (malformed workflow JSON)
Polling pattern
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/.
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())
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | query | string | Yes | UUID 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:
| Field | Type | Description |
|---|---|---|
status | integer | HTTP status from executor. 200 = response delivered. |
data | object | Executor response body. See nested fields below. |
data object fields:
| Field | Type | Description |
|---|---|---|
id | string | UUID of the workflow run (same as the query parameter). |
status | string | Overall run status. See allowed values below. |
data | object | Per-node results, keyed by node UUID (not node name). |
Allowed status Values
| Value | Meaning |
|---|---|
"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:
| Field | Type | Description |
|---|---|---|
id | string | Node UUID (same as the key). |
status | string | Node-level status. Same values as run-level status. |
result | object | Node output. Present only when node status is succeed. |
result object:
| Field | Type | Description |
|---|---|---|
content | string | Node 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 Status | Meaning |
|---|---|
400 | Missing id parameter, or run not found in database / no access. |
401 | Authentication credentials not provided. |
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:
| Format | Example | How 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. |
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
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.
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())
curl -X GET "https://scriptrun.ai/api/v1/workflows/6/history/?size=10&ordering=-created_at" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow. |
ordering | query | string | No | Sort field. Options: created_at, -created_at, cost, -cost. |
page | query | integer | No | Page number. |
size | query | integer | No | Number of items per page. |
Responses:
- 200: Returns a paginated list of workflow run history items.
- 404: Workflow not found.
History item fields:
| Field | Type | Description |
|---|---|---|
id | string | UUID of the run. |
created_at | string | When the run was created. |
updated_at | string | When the run was last updated. |
run_started_at | string | When execution started (null while queued). |
run_finished_at | string | When execution finished (null while running). |
status | string | Run status label (e.g. Succeeded, Error). |
result | object | Result payload of the run. |
data | object | Workflow structure the run was executed with. |
input_data | object | Input data the run was started with. |
input_fields | array | Trigger input fields of that run, same shape as input-fields. |
is_api_run | boolean | Whether this run is the workflow's API run. |
use_in_marketplace_example | boolean | Whether this run is shown as a marketplace example. |
use_as_marketplace_template | boolean | Whether this run is the marketplace template. |
cost | object | Run cost, converted to the available currencies. |
duration | number | Run duration in seconds (null if it never finished). |
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.
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())
curl -X GET "https://scriptrun.ai/api/v1/workflows/6/history/d2d20381-85c5-4a2d-8680-a2134dc8854f/" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow. |
run_id | path | string | Yes | UUID 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.
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())
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow. |
run_id | path | string | Yes | UUID 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.
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())
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow. |
run_id | path | string | Yes | UUID of the workflow run. |
Request Body:
| Name | Type | Required | Description |
|---|---|---|---|
is_api_run | boolean | Yes | New 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.
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow. |
run_id | path | string | Yes | UUID of the workflow run. |
Request Body:
| Name | Type | Required | Description |
|---|---|---|---|
use_in_marketplace_example | boolean | Yes | New 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.
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID of the workflow. |
run_id | path | string | Yes | UUID of the workflow run. |
Request Body:
| Name | Type | Required | Description |
|---|---|---|---|
use_as_marketplace_template | boolean | Yes | New 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.
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())
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:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id | path | string | Yes | UUID of the workflow run. |
page | query | integer | No | Page number, starting at 1. Defaults to 1. |
size | query | integer | No | Items per page (1–100). Defaults to 10. |
Response (200): a paginated envelope — items, page, size, total — where each item is:
| Field | Type | Description |
|---|---|---|
id | string | Transaction identifier. |
operation | string | Transaction type. |
status | string | Status of the node charge. Failed nodes are reported as Error. |
amount | object | Charged amount, converted to the available currencies. |
reason | string | Reason recorded for the transaction. |
description | string | Label of the node the charge belongs to. |
run_id | string | UUID of the workflow run. |
user_id | integer | ID of the charged user. |
created_at | string | When the transaction was created. |
updated_at | string | When 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.
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())
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.
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):
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workflow_run_id | path | string | Yes | UUID of the workflow run that is waiting. |
request_id | path | string | Yes | Identifier 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
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_resultimmediately after detecting a"succeed"status,data.datamay be partially populated or empty.
Recommended retry strategy:
- Poll
workflow_resultevery 3–5 seconds while status is non-terminal. - When status becomes
"succeed"or"failed", verify thatdata.datais non-empty and contains the expected output nodes. - If
data.datais empty or missing expected nodes despite a terminal status, wait 2–3 seconds and retry (up to 3 retries). - Only finalize your result after both conditions are true: terminal status AND non-empty
data.data.
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.
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())
curl -X GET "https://scriptrun.ai/api/v1/all-workflows/?search=classification&ordering=-last_run_at" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
search | query | string | No | Case-insensitive match on the workflow title or marketplace title. |
title__icontains | query | string | No | Case-insensitive match on the workflow title. |
project | query | integer | No | Filter by project ID. |
categories | query | integer | No | Filter by category ID. Repeat the parameter for several categories. |
subcategories | query | integer | No | Filter by subcategory ID. Repeat the parameter for several subcategories. |
languages | query | string | No | Comma-separated language codes; matches workflows available in any of them. |
own_scripts | query | boolean | No | Only workflows you authored. Defaults to false. |
ordering | query | string | No | Sort field: last_run_at, total_cost, created_at, each also with a - prefix. Bookmarked workflows stay on top. |
page | query | integer | No | Page number. |
size | query | integer | No | Number of items per page. |
Responses:
- 200: Returns a paginated list of workflows, including
is_bookmarked,last_run_at,last_run_cost,average_run_durationandtotal_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.
curl -X GET "https://scriptrun.ai/api/v1/all-workflows/6/" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | integer | Yes | ID 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.
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.
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.
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())
curl -X GET "https://scriptrun.ai/api/v1/workflows/marketplace/?search=seo&ordering=-last_run_at"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
search | query | string | No | Case-insensitive match on the marketplace title. |
categories | query | integer | No | Filter by category ID. Repeat the parameter for several categories. |
subcategories | query | integer | No | Filter by subcategory ID. Repeat for several subcategories. |
languages | query | string | No | Comma-separated language codes. |
marketplace_date_last_publication_after | query | string | No | Only workflows published on or after this date (YYYY-MM-DD). |
marketplace_date_last_publication_before | query | string | No | Only workflows published on or before this date (YYYY-MM-DD). |
ordering | query | string | No | Sort field: total_cost (average marketplace price), last_run_at, created_at, each also with a - prefix. |
page | query | integer | No | Page number. |
size | query | integer | No | Number of items per page. |
Responses:
- 200: Returns a paginated list of marketplace workflows.
Marketplace workflow fields (most relevant ones):
| Field | Type | Description |
|---|---|---|
id | integer | ID of the source workflow. |
slug | string | Marketplace identifier used in the URLs of these endpoints. |
market_title | string | Title shown on the marketplace. |
short_description | string | Short marketplace description. |
readme_guide | string | Long-form usage guide. |
available_languages | array | Language codes the workflow is offered in. |
run_fee | string | Fee charged per run. |
free_runs_per_user | integer | Number of free runs granted to each user. |
marketplace_price_avg | object | Average run price, converted to the available currencies. |
copied_workflow_id | integer | ID of your copy of this workflow, or -1 if you have not copied it. |
total_users_count | integer | Number of users who copied the workflow. |
total_runs_count | integer | Total number of runs. |
last_run_at | string | When the workflow was last run. |
Retrieve a Marketplace Workflow
GET /api/v1/workflows/marketplace/{slug}/
Summary: Retrieves a single marketplace workflow.
curl -X GET "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | Yes | Marketplace 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.
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
curl -X POST "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/add-from-marketplace/" \
-H "X-Api-Key: <Your API Key>"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | Yes | Marketplace slug of the workflow. |
Responses:
- 201: Returns your copy of the workflow. Use its
idwith 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.
curl -X GET "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/examples/"
Response (200): an array of example runs.
| Field | Type | Description |
|---|---|---|
id | string | UUID of the example run. |
created_at | string | When the run was created. |
cost | object | Run cost, converted to available currencies. |
result | object | Result payload of the run. |
input_data | object | Input the run was started with. |
data | object | Workflow 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.
curl -X GET "https://scriptrun.ai/api/v1/workflows/marketplace/text-classification/examples/0781b175-2135-45ec-9063-ad3e0d929adc/"
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | Yes | Marketplace slug of the workflow. |
run_id | path | string | Yes | UUID 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 byGET /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. Saveresponse["data"]["id"]— this is the UUID for polling. - Use
GET /api/v1/workflows/workflow_result/?id=<run_uuid>to poll for results. Poll untildata.statusis"succeed"or"failed". - Use
GET /api/v1/workflows/{id}/history/to view past runs, andGET /api/v1/workflows/{id}/history/{run_id}/for a single one. - Use the
toggle-api-run,toggle-marketplace-exampleandtoggle-marketplace-useendpoints 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
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())
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
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
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
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:
| Syntax | Description | Example |
|---|---|---|
{{ 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
- Use descriptive field names:
user_nameinstead ofn - Validate required fields: Use Trigger node with required input fields
- Keep structure consistent: Use the same data structure for similar workflows
- Test with sample data: Verify your variables work before running in production
- Handle
result.contentdefensively: Always parse it — it may be plain text, JSON, or markdown-wrapped JSON (see result.content formats) - 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
statusfield) - 400: Invalid input data or workflow structure
- 404: Workflow not found