Rate limitsSandbox: 1,000 req/min·Starter: 300 req/min·Growth: 1,000 req/min·Enterprise: Custom429 responses include a Retry-After header
Authentication
All API requests must include a valid API key in the Authorization header as a Bearer token. API keys are available in Settings → API Keys.
1Authorization: Bearer flw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Authenticate a request
1<?php2$api_key = 'flw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';3 4$ch = curl_init('https://app.flow80.com/api/v1/flows');5curl_setopt_array($ch, [6 CURLOPT_HTTPHEADER => [7 'Authorization: Bearer ' . $api_key,8 'Content-Type: application/json',9 ],10 CURLOPT_RETURNTRANSFER => true,11]);12$res = curl_exec($ch);13$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);14curl_close($ch);
1import requests2 3API_KEY = "flw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"4 5headers = {6 "Authorization": f"Bearer {API_KEY}",7 "Content-Type": "application/json",8}9 10resp = requests.get(f"https://app.flow80.com/api/v1/flows", headers=headers)11print(resp.json())
1const API_KEY = 'flw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';2 3const resp = await fetch(`https://app.flow80.com/api/v1/flows`, {4 headers: {5 'Authorization': `Bearer ${API_KEY}`,6 'Content-Type': 'application/json',7 },8});9const data = await resp.json();10console.log(data);
1require 'net/http'2require 'json'3 4API_KEY = 'flw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'5uri = URI("https://app.flow80.com/api/v1/flows")6 7req = Net::HTTP::Get.new(uri)8req['Authorization'] = "Bearer #{API_KEY}"9req['Content-Type'] = 'application/json'10 11res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }12puts JSON.parse(res.body)
1package main2 3import (4 "fmt"5 "net/http"6 "io"7)8 9func main() {10 apiKey := "flw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"11 req, _ := http.NewRequest("GET", "https://app.flow80.com/api/v1/flows", nil)12 req.Header.Set("Authorization", "Bearer "+apiKey)13 req.Header.Set("Content-Type", "application/json")14 client := &http.Client{}15 resp, _ := client.Do(req)16 defer resp.Body.Close()17 body, _ := io.ReadAll(resp.Body)18 fmt.Println(string(body))19}
1curl -X GET "https://app.flow80.com/api/v1/flows" \2 -H "Authorization: Bearer flw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \3 -H "Content-Type: application/json"
Endpoints
Workflows
GET/api/v1/flows
Returns a paginated list of all workflows in your account. Includes status, trigger type, and last run timestamp.
GET/api/v1/flows/:id
Returns a single workflow by ID, including its step definitions and current configuration.
POST/api/v1/flows/execute
Triggers a workflow execution programmatically. Use this to integrate Flow80 into your own systems.
Request body
{
"flow_id": "wf_xxxxxxxxxxxxxxxx",
"trigger": "api",
"payload": {
"order_id": "ORD-12345",
"customer_email": "[email protected]"
}
}
GET/api/v1/flows/:id/runs
Returns the execution history for a specific workflow. Supports cursor-based pagination.
Webhooks
POST/api/v1/webhooks/inbound
Inbound webhook endpoint. Flow80 POSTs here when receiving events from integrated third-party services.
GET/api/v1/webhooks
List all configured outbound webhooks for your account.
POST/api/v1/webhooks
Register a new outbound webhook URL and event types.
Request body
{
"url": "https://your-app.com/webhooks/flow80",
"events": ["flow.completed", "flow.failed"],
"secret": "whsec_xxxxxxxxxxxxxxxx"
}
Account & Usage
GET/api/v1/account
Returns details about the authenticated account: plan, status, creation date, and billing info.
GET/api/v1/usage
Returns current API usage including executions used/remaining and rate limit status for the current window.
Trigger a workflow
1<?php2$ch = curl_init('https://app.flow80.com/api/v1/flows/execute');3curl_setopt_array($ch, [4 CURLOPT_HTTPHEADER => [5 'Authorization: Bearer ' . $api_key,6 'Content-Type: application/json',7 ],8 CURLOPT_POST => true,9 CURLOPT_POSTFIELDS => json_encode([10 'flow_id' => 'wf_xxxxxxxxxxxxxxxx',11 'trigger' => 'api',12 'payload' => ['order_id' => 'ORD-12345'],13 ]),14 CURLOPT_RETURNTRANSFER => true,15]);16$res = curl_exec($ch);17$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);18curl_close($ch);
1import requests2 3resp = requests.post(4 f"https://app.flow80.com/api/v1/flows/execute",5 headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},6 json={7 "flow_id": "wf_xxxxxxxxxxxxxxxx",8 "trigger": "api",9 "payload": {"order_id": "ORD-12345"},10 },11)12print(f"Status: {resp.status_code} — {resp.json()}")
1const resp = await fetch(`https://app.flow80.com/api/v1/flows/execute`, {2 method: 'POST',3 headers: {4 'Authorization': `Bearer ${API_KEY}`,5 'Content-Type': 'application/json',6 },7 body: JSON.stringify({8 flow_id: 'wf_xxxxxxxxxxxxxxxx',9 trigger: 'api',10 payload: { order_id: 'ORD-12345' },11 }),12});13const result = await resp.json();14console.log(result);
1require 'net/http'2require 'json'3 4uri = URI("https://app.flow80.com/api/v1/flows/execute")5req = Net::HTTP::Post.new(uri)6req['Authorization'] = "Bearer #{API_KEY}"7req['Content-Type'] = 'application/json'8req.body = JSON.generate({9 flow_id: 'wf_xxxxxxxxxxxxxxxx',10 trigger: 'api',11 payload: { order_id: 'ORD-12345' },12})13res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }14puts "Status: #{res.code}"
1// Build JSON payload2payload := `{"flow_id":"wf_xxxxxxxxxxxxxxxx","trigger":"api","payload":{"order_id":"ORD-12345"}}`3req, _ := http.NewRequest("POST", "https://app.flow80.com/api/v1/flows/execute", strings.NewReader(payload))4req.Header.Set("Authorization", "Bearer "+apiKey)5req.Header.Set("Content-Type", "application/json")6// ...
1curl -X POST "https://app.flow80.com/api/v1/flows/execute" \2 -H "Authorization: Bearer flw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \3 -H "Content-Type: application/json" \4 -d '{"flow_id":"wf_xxxxxxxxxxxxxxxx","trigger":"api","payload":{"order_id":"ORD-12345"}}'
Error Codes
400Bad RequestInvalid JSON or missing required fields.
401UnauthorizedMissing or invalid API key.
403ForbiddenValid key but insufficient permissions for this resource.
404Not FoundFlow, webhook, or resource does not exist.
422UnprocessableRequest valid but action cannot be performed (e.g., paused flow).
429Too Many RequestsRate limit exceeded. Check Retry-After header.
500Internal ErrorSomething wrong on our end. Retry with exponential backoff.