About
Roboflow Workflows are visual computer-vision pipelines you build in the web app and deploy as a hosted endpoint. This page covers the management surface - listing, retrieving, creating, and updating the Workflows in a workspace - through the REST API and Python SDK. To run a Workflow against an image or video stream, see the Workflows runtime docs.
HTTP API
Roboflow Workflows are visual computer-vision pipelines you can build in the web app and deploy as a hosted endpoint. The REST API exposes the management surface; for executing a workflow against an image or video stream, see Run a Model on an Image and the Workflows runtime docs.
api_key may be passed as a query parameter or in the request body. Required scopes are noted on each endpoint.
Project Base Workflows
Each Project has a base Workflow that backs its hosted model endpoint. Use these Project-scoped operations to read that Workflow or select the model used by its model step.
Get a Project Base Workflow
GET /:workspace/:project/deploy
Required scope: project:read
curl "https://api.roboflow.com/my-workspace/my-project/deploy?api_key=$ROBOFLOW_API_KEY"If the Project does not have a base Workflow, this request creates one. The response identifies the Project, its base Workflow, the selected model, its deployability, and its Active Learning state:
{
"project": {
"id": "abc123",
"url": "my-project",
"name": "My Project",
"owner": "my-workspace-id",
"type": "object-detection",
"classes": ["cat", "dog"],
"multilabel": false
},
"workflow": {
"id": "wf_xyz",
"name": "My Project Base Workflow",
"url": "my-project-base-workflow",
"workspaceUrl": "my-workspace",
"inferencePath": "/infer/workflows/my-workspace/my-project-base-workflow"
},
"model": {
"id": "rfdetr-medium",
"kind": "pretrained",
"displayName": "RF-DETR Medium",
"modelId": "rfdetr-medium"
},
"deployability": {
"status": "deployable",
"modelWasConfigured": false,
"selectedModelId": null,
"selectionReason": null
},
"activeLearning": {
"enabled": false,
"collectionLimits": {
"dataPercentage": 100,
"minutelyUsageLimit": 10,
"hourlyUsageLimit": 100,
"dailyUsageLimit": 1000,
"labelingBatchesRecreationFrequency": "daily",
"usageQuotaName": "upload_quota_active_learning",
"imageCompressionLevel": 95,
"maxImageHeight": 1080,
"maxImageWidth": 1920,
"persistPredictions": true
},
"filters": []
},
"baseWorkflowWasCreated": false
}model is null when no model is configured. deployability.status is "not_deployable" when the Workflow cannot serve inference. baseWorkflowWasCreated tells you whether this request created the base Workflow.
Select a Project Base Workflow Model
POST /:workspace/:project/deploy/model
Required scope: project:update
Set model.type to "model_id", "sam3", or "clip":
curl -X POST "https://api.roboflow.com/my-workspace/my-project/deploy/model" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'$ROBOFLOW_API_KEY'",
"model": {
"type": "model_id",
"modelId": "rfdetr-medium"
}
}'For "model_id", modelId is required. displayName and taskType are optional. For "sam3" and "clip", provide a non-empty classes array instead of modelId:
{
"api_key": "YOUR_API_KEY",
"model": {
"type": "sam3",
"classes": ["cat", "dog"]
}
}The response has the same shape as Get a Project Base Workflow. A 400 response means the model value is missing or invalid.
To enable data collection, set collection limits, or list images in the review queue, use the Active Learning HTTP API.
List Workflows
GET /:workspace/workflows
Lists all workflows in the workspace.
Query
| Name | Type | Description | Required |
|---|---|---|---|
api_key | string | API key for the workspace. | true |
Example Request
curl "https://api.roboflow.com/my-workspace/workflows?api_key=$ROBOFLOW_API_KEY"Response
{
"workflows": [
{
"id": "wf_abc123",
"name": "Slow webhooks",
"url": "slow-webhooks",
"createdAt": "2026-04-12T17:05:33.000Z"
}
],
"status": "ok"
}Required scope: workflow:read.
Get a Workflow
GET /:workspace/workflows/:workflowUrl
Returns the workflow's specification, metadata, and (for non-public workflows) authorization status.
curl "https://api.roboflow.com/my-workspace/workflows/slow-webhooks?api_key=$ROBOFLOW_API_KEY"Public workflows can be accessed without an api_key. Private workflows require the workflow:read scope.
List Workflow Versions
GET /:workspace/workflows/:workflowUrl/versions
curl "https://api.roboflow.com/my-workspace/workflows/slow-webhooks/versions?api_key=$ROBOFLOW_API_KEY"Returns the versioned snapshots of the workflow specification.
Create a Workflow
POST /:workspace/createWorkflow
Headers
| Name | Value |
|---|---|
| Content-Type | application/json |
Body
| Name | Type | Description | Required |
|---|---|---|---|
api_key | string | Workspace API key. | true |
name | string | Display name. | true |
url | string | URL slug for the workflow. | true |
config | string | JSON-encoded workflow specification (see note below). | true |
template | string | JSON-encoded template metadata. Pass "{}" if you don't have one. | false |
Note on config: the API expects the stored shape {"specification": {...}}. Passing a bare specification works through the SDK adapter, which auto-wraps it; for direct REST calls, wrap it yourself.
Example Request
curl -X POST "https://api.roboflow.com/my-workspace/createWorkflow" \
-H 'Content-Type: application/json' \
-d '{"api_key":"'$ROBOFLOW_API_KEY'","name":"My Workflow","url":"my-workflow","config":"{\"specification\":{\"version\":\"1.0\",\"inputs\":[],\"steps\":[],\"outputs\":[]}}"}'You can also send the same fields as query parameters, but then template is required. Use the body for large specifications, since long URLs get cut off.
curl -X POST "https://api.roboflow.com/my-workspace/createWorkflow" \
--get \
--data-urlencode "api_key=$ROBOFLOW_API_KEY" \
--data-urlencode "name=My Workflow" \
--data-urlencode "url=my-workflow" \
--data-urlencode 'config={"specification":{"version":"1.0","inputs":[],"steps":[],"outputs":[]}}' \
--data-urlencode 'template={}'Response
{
"workflows": { "id": "wf_xyz789", "url": "my-workflow" },
"status": "ok"
}Required scope: workflow:create.
Update a Workflow
POST /:workspace/updateWorkflow
Headers
| Name | Value |
|---|---|
| Content-Type | application/json |
Body
| Name | Type | Description | Required |
|---|---|---|---|
id | string | Workflow's internal ID. | true |
name | string | Display name. | true |
url | string | URL slug. | true |
config | string | JSON-encoded workflow specification (see note on Create). | true |
curl -X POST "https://api.roboflow.com/my-workspace/updateWorkflow?api_key=$ROBOFLOW_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id":"wf_xyz789","name":"My Workflow","url":"my-workflow","config":"{\"specification\":{\"version\":\"1.0\",\"steps\":[]}}"}'Required scope: workflow:update.
Fork a Workflow
POST /:workspace/forkWorkflow
Copy a workflow from another workspace into this one.
Body
| Name | Type | Description | Required |
|---|---|---|---|
source_workspace | string | Slug of the workspace that owns the source workflow. | true |
source_workflow | string | URL slug of the source workflow. | true |
name | string | Display name for the fork. Defaults to source name. | false |
url | string | URL slug for the fork. Auto-generated if omitted. | false |
curl -X POST "https://api.roboflow.com/my-workspace/forkWorkflow?api_key=$ROBOFLOW_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"source_workspace":"other-workspace","source_workflow":"their-workflow","name":"My Fork","url":"my-fork"}'Required scope: workflow:create.
Generate a Workflow Token
POST /:workspace/workflowToken
Generate a short-lived token suitable for executing a workflow from a public client (e.g. a browser).
curl -X POST "https://api.roboflow.com/my-workspace/workflowToken?api_key=$ROBOFLOW_API_KEY"Delete (soft-delete) a Workflow
DELETE /:workspace/workflows/:workflowUrl
Moves the workflow to Trash. See Manage Trash for the response shape and restore flow.
Run a Workflow
Workflow execution lives at https://serverless.roboflow.com, not the management API. See Run a Model on an Image and the product docs on deploying a workflow.
Python SDK
Roboflow Workflows are visual computer-vision pipelines. The SDK exposes list / get / create directly on Workspace; update, fork, and delete live in the low-level rfapi adapter.
List workflows
import roboflow
rf = roboflow.Roboflow(api_key="YOUR_API_KEY")
workspace = rf.workspace()
workflows = workspace.list_workflows()
for w in workflows:
print(w["id"], w["name"], w["url"])Get a workflow
workflow = workspace.get_workflow("slow-webhooks")
print(workflow["specification"])The url argument is the workflow's slug (visible in the web app's URL bar) - not its Firestore id.
Create a workflow
workflow = workspace.create_workflow(
name="My Workflow",
definition={
"version": "1.0",
"inputs": [...],
"steps": [...],
"outputs": [...],
},
)
print(workflow["id"], workflow["url"])Pass definition=None to create an empty workflow shell that you'll edit in the web app afterwards.
The SDK accepts either a bare specification dict ({"version": ..., "steps": ...}) or a wrapped one ({"specification": {...}}); it normalizes the wrapping for you and strips a UTF-8 BOM if present.
Update a workflow
Workspace doesn't expose update directly - use the low-level adapter:
from roboflow.adapters import rfapi
rfapi.update_workflow(
api_key="YOUR_API_KEY",
workspace_url=workspace.url,
workflow_id=workflow["id"],
workflow_name="My Workflow",
workflow_url="my-workflow",
config={"version": "1.0", "steps": [...]},
)Fork a workflow
Copy a workflow from another workspace into your own. Useful for adopting a public template:
from roboflow.adapters import rfapi
forked = rfapi.fork_workflow(
api_key="YOUR_API_KEY",
workspace_url=workspace.url,
source_workspace="other-workspace",
source_workflow="their-workflow",
name="My Fork", # optional; defaults to the source name
url="my-fork", # optional; defaults to a generated slug
)List workflow versions
versions = rfapi.list_workflow_versions(
api_key="YOUR_API_KEY",
workspace_url=workspace.url,
workflow_url="my-workflow",
)Delete (soft-delete) a workflow
rfapi.delete_workflow(api_key="YOUR_API_KEY", workspace_url=workspace.url, workflow_url="my-workflow")This moves the workflow to the workspace Trash where it remains for 30 days before permanent cleanup. Restore via Workspace.restore_from_trash("workflow", id) - see Delete and Restore.
Run a workflow
Workflow execution lives in the Inference SDK and the Workflows runtime, not the roboflow package. From Python:
from inference_sdk import InferenceHTTPClient
client = InferenceHTTPClient(
api_url="https://serverless.roboflow.com",
api_key="YOUR_API_KEY",
)
result = client.run_workflow(
workspace_name="my-workspace",
workflow_id="my-workflow",
images={"image": "photo.jpg"},
)CLI
You can list, create, update, fork, and version workflows from the command line.
List Workflows
roboflow workflow listroboflow workflow list --jsonGet Workflow Details
roboflow workflow get my-workflowroboflow workflow get my-workflow --jsonCreate a Workflow
roboflow workflow create --name "My Workflow"With a JSON definition file:
roboflow workflow create --name "My Workflow" --definition workflow.jsonOptions
| Flag | Description |
|---|---|
--name | Workflow name (required) |
--definition | Path to JSON definition file |
--description | Workflow description |
Update a Workflow
Update a workflow's definition:
roboflow workflow update my-workflow --definition updated.jsonList Workflow Versions
roboflow workflow version list my-workflowroboflow workflow version list my-workflow --jsonFork a Workflow
Fork a workflow from the current workspace:
roboflow workflow fork my-workflowFork from another workspace:
roboflow workflow fork other-workspace/their-workflowJSON Output
All workflow commands support --json for structured output:
roboflow workflow list --json | jq '.[].name'
roboflow workflow create --name "Test" --jsonExit codes: 0 = success, 1 = error, 2 = auth error, 3 = not found.
MCP Server
Connect your AI agent to the MCP Server and it can build and run Workflows with these tools:
| Tool | Description |
|---|---|
workflows_list | List saved Workflows in the workspace. |
workflows_get | Get details for a saved Workflow. |
workflows_create | Create and save a new Workflow. |
workflows_update | Update a saved Workflow's name and definition. |
workflows_run | Execute a saved Workflow on one or more images. |
workflows_delete | Delete a saved Workflow, moving it to the workspace Trash. |