Build AI + human workflow products on top of Orchflow.
These docs cover the practical flow: register, start a run, inspect tasks, pause for human input, resume, and optionally attach your own provider key.
From zero to first run
The fastest path is: register, start a run, then add a provider later if you need more control.
If you are evaluating Orchflow for the first time, use the hosted flow first. That lets you see task planning, human checkpoints, and run completion before you spend time on provider setup.
1. Register
Create an account and receive an API key once.
2. Start a run
Use the hosted flow first with the managed trial runs.
3. Resume human tasks
When Orchflow pauses, send the human response and continue execution.
What this does: starts one tracked run. Replace orch_your_key, keep the built-in agent names, and edit ask_me_about to the facts your app should collect from the user.
curl -X POST https://api.orchflow.cloud/api/v1/runs \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{
"task": "Plan and launch a faceless YouTube channel about AI tools for freelancers.",
"agents": [
{ "name": "research" },
{ "name": "analyst" },
{ "name": "writer" }
],
"ask_me_about": ["brand voice", "target audience"],
"require_approval": false
}'
The loop is only three moves: poll the run, answer a waiting human task if Orchflow asks, then poll again until status is completed.
# 1. Inspect the run
curl https://api.orchflow.cloud/api/v1/runs/run_abc123 \
-H "X-API-Key: orch_your_key"
# 2. If status is waiting_human, answer that task
curl -X POST https://api.orchflow.cloud/api/v1/runs/run_abc123/tasks/T1/complete \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{"output":"Company: a workflow API for AI apps. Brand voice: direct, useful, technical."}'
# 3. Poll the same run again to watch AI continue
curl https://api.orchflow.cloud/api/v1/runs/run_abc123 \
-H "X-API-Key: orch_your_key"
How API keys work
Orchflow returns a raw API key once at registration time. After that, only the hash is stored.
Registration is intentionally lightweight. Orchflow returns the raw API key once, and every protected route after that expects it in the request header.
{
"name": "Tarun",
"email": "tarun@example.com"
}
curl -X POST https://api.orchflow.cloud/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"Tarun","email":"tarun@example.com"}'
| Header | Value | Required |
|---|---|---|
X-API-Key |
Your Orchflow API key | Yes, for protected routes |
Start, inspect, and cancel runs
The runs API is the heart of Orchflow. One request starts a workflow and returns a `run_id` immediately.
Think of a run as the top-level workflow container. You send one goal, Orchflow creates the task graph, executes what it can, and keeps the full run state available while work is in progress.
{
"task": "Research 5 competitors, extract pricing, compare positioning, then propose our launch strategy.",
"ask_me_about": ["company details"],
"require_approval": false
}
curl -X POST https://api.orchflow.cloud/api/v1/runs \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{
"task":"Research 5 competitors, extract pricing, compare positioning, then propose our launch strategy.",
"ask_me_about":["company details"],
"require_approval":false
}'
curl 'https://api.orchflow.cloud/api/v1/runs?limit=10&offset=0' \
-H "X-API-Key: orch_your_key"
curl https://api.orchflow.cloud/api/v1/runs/run_abc123 \
-H "X-API-Key: orch_your_key"
curl https://api.orchflow.cloud/api/v1/runs/run_abc123/tasks \
-H "X-API-Key: orch_your_key"
curl -X DELETE https://api.orchflow.cloud/api/v1/runs/run_abc123 \
-H "X-API-Key: orch_your_key"
Resume tasks when Orchflow pauses
When a task needs human input, the run moves to `waiting_human`. Submit the answer and the run continues automatically.
Human tasks are what make Orchflow useful for real products. When the workflow needs brand context, approval, or judgment, it pauses instead of hallucinating past the missing information.
{
"output": "Brand voice should be practical and founder-friendly. Target audience is solo freelancers and small agencies."
}
curl -X POST https://api.orchflow.cloud/api/v1/runs/run_abc123/tasks/T1/complete \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{"output":"Company details: we build workflow APIs. Brand voice: direct and technical."}'
- Use `ask_me_about` when you want Orchflow to explicitly ask for missing context.
- Use `human_gates` when you want to route matching tasks to humans.
- Use `require_approval=true` when every task must wait for human approval.
Register and manage LLM providers
Provider keys are encrypted before storage. The raw key is never returned after registration.
Providers are optional for the first managed trial runs in hosted mode. After that, use `provider_id` in `POST /runs` so Orchflow knows which model account to execute against.
{
"provider": "gemini",
"api_key": "your_provider_key",
"label": "My Gemini key",
"model": "gemini-3.1-flash-lite-preview"
}
curl https://api.orchflow.cloud/api/v1/providers \
-H "X-API-Key: orch_your_key"
curl -X DELETE https://api.orchflow.cloud/api/v1/providers/prv_abc123 \
-H "X-API-Key: orch_your_key"
Use this after the managed trial, or whenever you want your own model account. Register the provider once. Orchflow stores the encrypted key and returns a provider_id. Future runs use that id, not the raw provider key.
# 1. Register your provider key once
curl -X POST https://api.orchflow.cloud/api/v1/providers \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{
"provider": "gemini",
"api_key": "your_gemini_api_key",
"label": "My Gemini key",
"model": "gemini-2.0-flash-lite"
}'
# Response:
# { "provider_id": "prv_abc123", ... }
# 2. Pass provider_id when starting a run
curl -X POST https://api.orchflow.cloud/api/v1/runs \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{
"task": "Research competitors and draft a launch strategy.",
"provider_id": "prv_abc123",
"agents": [{ "name": "research" }, { "name": "writer" }],
"ask_me_about": ["company details"],
"require_approval": false
}'
Use built-in named agents
For the fastest first run, you can pass agent names only and let Orchflow fill the built-in templates.
Built-in templates are the fastest path for first runs. You can pass only the agent names and let Orchflow fill the system prompts automatically.
curl https://api.orchflow.cloud/api/v1/agents/templates
{
"agents": [
{ "name": "research" },
{ "name": "analyst" },
{ "name": "writer" }
]
}
Embed Orchflow into your own app
Most teams will call Orchflow from their backend, persist the `run_id` in their own database, and show progress or approval steps in their own UI.
The usual pattern is simple: your app starts a run, stores the returned `run_id`, polls or listens for status changes, and submits human responses when Orchflow pauses.
Start from your backend
Use your server to call Orchflow so your app controls when workflows begin and how the resulting `run_id` is stored.
Show progress in your UI
Read `GET /runs/{id}` or `GET /runs/{id}/tasks` and render task states in your own product interface.
Resume after human input
When a run pauses, your UI can capture approval or missing context and pass it back through the task completion endpoint.
This is the important developer loop. Start a run, poll task progress, print what Orchflow is doing, and stop with a clear task_id when the workflow needs human input.
import time
import requests
API = "https://api.orchflow.cloud/api/v1"
api_key = "orch_your_key"
headers = {"X-API-Key": api_key}
def orchflow(method, path, **kwargs):
response = requests.request(method, f"{API}{path}", headers=headers, timeout=60, **kwargs)
if not response.ok:
raise RuntimeError(f"Orchflow {response.status_code}: {response.text}")
return response.json()
run = orchflow("POST", "/runs", json={
"task": "Research competitors, compare pricing, then draft our launch strategy.",
"agents": [{"name": "research"}, {"name": "analyst"}, {"name": "writer"}],
"ask_me_about": ["company details", "brand voice"],
"require_approval": False
})
run_id = run["run_id"]
print("Started run:", run_id)
while True:
run = orchflow("GET", f"/runs/{run_id}")
print("\nRun status:", run["status"])
for task_id, task in run["subtasks"].items():
print(f"{task_id}: {task['state']} - {task['name']}")
waiting = [
(task_id, task)
for task_id, task in run["subtasks"].items()
if task["state"] == "waiting_human"
]
if waiting:
task_id, task = waiting[0]
print(f"\nAction needed: answer task {task_id} - {task['name']}")
break
if run["status"] in ["completed", "failed", "cancelled"]:
print("\nFinal output:", run.get("final_output"))
break
time.sleep(3)
Run this when the watcher prints Action needed. Replace T1 with the printed task id. After this POST succeeds, run the watcher again or keep polling from your app.
import requests
api_key = "orch_your_key"
run_id = "run_abc123"
task_id = "T1"
response = requests.post(
f"https://api.orchflow.cloud/api/v1/runs/{run_id}/tasks/{task_id}/complete",
headers={"X-API-Key": api_key},
json={
"output": "Company: a workflow API for AI apps. Brand voice: direct, useful, technical."
},
timeout=30
)
response.raise_for_status()
print("Submitted human input. Continue polling the run.")
For a production app, proxy this through your backend. This minimal browser example shows the polling shape, but keeping API keys in a server session is safer than embedding them in client code.
const res = await fetch(`https://api.orchflow.cloud/api/v1/runs/${runId}`, {
headers: { "X-API-Key": apiKey }
});
const run = await res.json();
if (run.status === "waiting_human") {
// Show approval form or collect missing context in your UI
}
Common responses
These are the most common API responses you should expect during development.
Most development issues come from missing API keys, consumed trial runs, invalid payloads, or polling too aggressively. The table below covers the usual fixes.
| Status | Meaning | Typical fix |
|---|---|---|
| 401 | Missing or invalid API key | Pass a valid `X-API-Key` header |
| 402 | Managed trial runs used up or BYOK required | Register a provider and pass `provider_id` |
| 404 | Run, task, or provider not found | Check the ID and ownership |
| 422 | Validation error | Check body shape, prompt fields, and required values |
| 429 | Rate limit exceeded | Retry later or slow down polling |
Good first tasks to try
Use tasks where Orchflow can show planning, routing, human checkpoints, and synthesis clearly.
The best demos are tasks with clear planning value: some parallel work, one or two human checkpoints, and a final output that is obviously stronger than a one-shot model response.
Content workflow
Research, writing, editing, then final approval before publishing.
Competitor analysis
Extract pricing, compare positioning, ask for company context, then produce strategy.
Architecture planning
Design the system, review security/billing risks, and produce an implementation roadmap.
{
"task": "Plan and launch a faceless YouTube channel about AI tools for freelancers. Research 5 competing channels, extract their content patterns, define our positioning, decide the branding direction, design a 30-day content plan, and produce a launch checklist.",
"agents": [
{ "name": "research" },
{ "name": "analyst" },
{ "name": "writer" }
],
"ask_me_about": ["brand voice", "target audience", "content constraints"],
"require_approval": false
}