Recipes
Short, copy-pasteable workflows that combine a few endpoints. All examples assume fr_your_api_key and a known project_id.
Generate a filtered handoff
Generate a handoff for only the main branch of one repo, then poll for the result.
# 1. Enqueue
curl "https://www.flowrelay.it/api/v1/handoffs" \
-H "Authorization: Bearer fr_your_api_key" \
-X POST \
-H "Content-Type: application/json" \
-d '{ "project_id": "proj_8c1d", "sources": ["github"], "filters": { "github": { "branches": ["main"] } } }'
# 2. Poll (repeat until status is completed)
curl "https://www.flowrelay.it/api/v1/jobs/job_9f3c" \
-H "Authorization: Bearer fr_your_api_key"Discover valid branch and repo values first with GET /handoffs/filters – see Filters.
Find untracked resources
List active resources that are producing events but are not yet assigned to any project, so you can decide what to add.
curl "https://www.flowrelay.it/api/v1/integrations/untracked" \
-H "Authorization: Bearer fr_your_api_key"[
{ "source": "slack", "resource_id": "C0123", "resource_name": "#incidents", "event_count": 42 }
]The response is a bare array sorted by most recent activity.
Post a summary to Discord
Send a message to a channel in your connected Discord server – for example, to announce a fresh handoff.
async function announce(apiKey, channelId, text) {
const res = await fetch("https://www.flowrelay.it/api/v1/discord/send", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ channel_id: channelId, content: text }),
});
return res.json();
}List channel ids first with GET /discord/channels. The target channel must belong to your connected guild, or the call returns 403.
End to end: generate, then announce
Chain the two: generate a handoff, wait for it, then post a link.
import requests, time
BASE = "https://www.flowrelay.it/api/v1"
HEADERS = {"Authorization": "Bearer fr_your_api_key"}
job = requests.post(
f"{BASE}/handoffs", headers=HEADERS, json={"project_id": "proj_8c1d"}
).json()
job_id = job["jobId"]
while True:
payload = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS).json()
if payload["job"]["status"] in ("completed", "failed"):
break
time.sleep(2)
handoff = payload["result"]
requests.post(
f"{BASE}/discord/send",
headers=HEADERS,
json={"channel_id": "987654", "content": f"New handoff: {handoff['title']}"},
)See Async jobs for a hardened polling loop with a timeout.