API reference
Every endpoint is authenticated with a bearer API key and lives under https://www.flowrelay.it/api/v1. Rate limit: 60 requests / minute / key.
openapi.json into Postman or Insomnia to generate a client.List accessible projects
/projectsReturns the tenant context for the key owner: account type, organization memberships, and every personal or organization project the key can access (role-scoped).
Request
curl "https://www.flowrelay.it/api/v1/projects" \
-H "Authorization: Bearer fr_your_api_key"Response
{
"account_type": "business",
"organizations": [
{
"id": "org_3f2a",
"name": "Acme",
"slug": "acme",
"role": "admin",
"is_temporary_admin": false
}
],
"projects": [
{
"id": "proj_8c1d",
"name": "Payments",
"slug": "payments",
"description": "Billing and checkout",
"organization_id": "org_3f2a",
"organization_name": "Acme",
"organization_slug": "acme",
"project_type": "organization",
"access_role": "admin",
"created_at": "2026-05-01T09:12:00Z",
"updated_at": "2026-06-20T14:03:00Z"
}
]
}| Status | When |
|---|---|
| 200 | Success |
| 401 | Missing or invalid API key. |
| 429 | Rate limit exceeded (60/min/key). |
List handoffs
/handoffsLists handoffs across accessible projects, newest first. Without project_id it spans every project the key can access.
Query parameters
| Name | Type | Description |
|---|---|---|
statusoptional | string | Filter by status.One of: active, archived, allDefault: active |
limitoptional | integer | Maximum rows to return (1–100).Default: 20 |
project_idoptional | string | Restrict to a single project. |
Request
curl "https://www.flowrelay.it/api/v1/handoffs" \
-H "Authorization: Bearer fr_your_api_key"Response
{
"handoffs": [
{
"id": "ho_1a2b",
"project_id": "proj_8c1d",
"title": "Checkout refactor handoff",
"summary": "Migrated the checkout flow to the new pricing engine.",
"status": "active",
"sources": [
"github",
"linear"
],
"key_changes": [
"Replaced legacy tax calc"
],
"decisions": [
"Use flat per-artifact pricing"
],
"open_questions": [
"Backfill historical invoices?"
],
"next_steps": [
"Wire the new webhook"
],
"related_event_ids": [
"ev_44ff"
],
"scope_type": "project",
"project_name": "Payments",
"created_at": "2026-06-20T14:03:00Z",
"updated_at": "2026-06-20T14:03:00Z"
}
]
}| Status | When |
|---|---|
| 200 | Success |
| 401 | Missing or invalid API key. |
| 404 | Project not found or not accessible by this key. |
Generate a handoff
/handoffsAsynchronous – returns 202 with a jobId. Poll GET /jobs/{jobId} until the job completes.
Enqueues a project handoff generation and returns a job id. Poll GET /jobs/{jobId} until status is completed. When sources/filters are omitted the project saved scope preferences are used.
Body parameters
| Name | Type | Description |
|---|---|---|
project_idrequired | string | Project to generate the handoff for. |
sourcesoptional | string[] | Restrict generation to these sources (e.g. ["github","slack"]). |
filtersoptional | SourceFilter | Per-source projects / eventTypes / branches / priorities (AND-combined). |
Request
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", "linear" ], "filters": { "github": { "branches": [ "main" ] } } }'Request body
{
"project_id": "proj_8c1d",
"sources": [
"github",
"linear"
],
"filters": {
"github": {
"branches": [
"main"
]
}
}
}Response
{
"jobId": "job_9f3c",
"status": "pending"
}| Status | When |
|---|---|
| 202 | Job enqueued. Poll GET /jobs/{jobId} for the result. |
| 400 | project_id is missing. |
| 401 | Missing or invalid API key. |
| 404 | Project not found or not accessible by this key. |
| 429 | Rate limit exceeded (60/min/key). |
List selectable filter options
/handoffs/filtersReturns the real selectable filter values per connected source for a project: resources (repos / channels / boards), branches, event types, and priorities. Use these to build a valid SourceFilter instead of guessing.
Query parameters
| Name | Type | Description |
|---|---|---|
project_idrequired | string | Project to resolve filter options for. |
Request
curl "https://www.flowrelay.it/api/v1/handoffs/filters?project_id=PROJECT_ID" \
-H "Authorization: Bearer fr_your_api_key"Response
{
"filters": {
"github": {
"projects": [
{
"id": "acme/payments",
"label": "acme/payments"
}
],
"eventTypes": [
{
"value": "push",
"label": "Push"
}
],
"priorities": [],
"branches": [
{
"value": "main",
"label": "main"
}
]
},
"linear": {
"projects": [
{
"id": "team_x",
"label": "Core"
}
],
"eventTypes": [
{
"value": "issue",
"label": "Issue"
}
],
"priorities": [
{
"value": "high",
"label": "High"
}
]
}
}
}| Status | When |
|---|---|
| 200 | Success |
| 400 | project_id is missing. |
| 401 | Missing or invalid API key. |
| 404 | Project not found or not accessible by this key. |
List project insights
/projects/{id}/insightsLists AI insights for a project, newest first. Optionally filter by kind and status.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Project id. |
Query parameters
| Name | Type | Description |
|---|---|---|
kindoptional | string | Filter by insight kind.One of: cross_source_correlation, onboarding_brief, architecture_insight |
statusoptional | string | Filter by status.One of: active, archived, allDefault: active |
limitoptional | integer | Maximum rows to return (1–100).Default: 20 |
Request
curl "https://www.flowrelay.it/api/v1/projects/PROJECT_ID/insights" \
-H "Authorization: Bearer fr_your_api_key"Response
{
"insights": [
{
"id": "ins_7b2e",
"project_id": "proj_8c1d",
"kind": "architecture_insight",
"title": "Pricing engine trade-offs",
"summary": "Flat per-artifact pricing simplifies billing at the cost of margin variance.",
"data": {
"tradeOffs": [],
"risks": [],
"patterns": [],
"recommendations": []
},
"model_used": "gemini-2.5-flash",
"status": "active",
"related_event_ids": [
"ev_44ff"
],
"created_at": "2026-06-21T08:00:00Z",
"updated_at": "2026-06-21T08:00:00Z"
}
]
}| Status | When |
|---|---|
| 200 | Success |
| 401 | Missing or invalid API key. |
| 404 | Project not found or not accessible by this key. |
Generate an insight
/projects/{id}/insights/{kind}Asynchronous – returns 202 with a jobId. Poll GET /jobs/{jobId} until the job completes.
Enqueues an insight generation for the project and returns a job id. The accepted body fields depend on kind. Poll GET /jobs/{jobId} for the result.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Project id. |
kindrequired | string | Insight kind.One of: correlation, onboarding, architecture |
Body parameters
| Name | Type | Description |
|---|---|---|
lookbackHoursoptional | integer | correlation only – window in hours (default 168). |
lookbackDaysoptional | integer | onboarding / architecture – window in days (30 / 14 default). |
newMemberRoleoptional | string | onboarding only – role of the person being onboarded. |
focusAreaoptional | string | onboarding only – area to emphasise. |
focusQuestionoptional | string | architecture only – the question to investigate. |
sourcesoptional | string[] | Restrict to these sources. |
filtersoptional | SourceFilter | Per-source filters (AND-combined). |
maxEventsoptional | integer | Cap the events fed to the model. |
Request
curl "https://www.flowrelay.it/api/v1/projects/PROJECT_ID/insights/architecture" \
-H "Authorization: Bearer fr_your_api_key" \
-X POST \
-H "Content-Type: application/json" \
-d '{ "focusQuestion": "Is the pricing engine coupling billing to providers?", "lookbackDays": 14 }'Request body
{
"focusQuestion": "Is the pricing engine coupling billing to providers?",
"lookbackDays": 14
}Response
{
"jobId": "job_2d4a",
"status": "pending"
}| Status | When |
|---|---|
| 202 | Job enqueued. Poll GET /jobs/{jobId} for the result. |
| 400 | Unsupported insight kind. |
| 401 | Missing or invalid API key. |
| 404 | Project not found or not accessible by this key. |
| 429 | Rate limit exceeded (60/min/key). |
List context events
/eventsLists recent context events, newest first. With project_id it spans the project members and scoped sources; without it returns the key owner personal-stream events.
Query parameters
| Name | Type | Description |
|---|---|---|
sourceoptional | string | Filter by source (e.g. github, slack, linear). |
limitoptional | integer | Maximum rows to return (1–200).Default: 50 |
project_idoptional | string | Restrict to a project scope. |
Request
curl "https://www.flowrelay.it/api/v1/events" \
-H "Authorization: Bearer fr_your_api_key"Response
{
"events": [
{
"id": "ev_44ff",
"user_id": "usr_1",
"source": "github",
"event_type": "push",
"title": "Push to acme/payments",
"content": "3 commits on main",
"created_at": "2026-06-20T13:55:00Z"
}
]
}| Status | When |
|---|---|
| 200 | Success |
| 401 | Missing or invalid API key. |
| 404 | Project not found or not accessible by this key. |
List integrations
/integrationsLists connected integrations. With project_id it returns the project-scoped resources with health and provider coverage; without it returns the key owner connected sources.
Query parameters
| Name | Type | Description |
|---|---|---|
project_idoptional | string | Return project-scoped integrations instead of personal ones. |
Request
curl "https://www.flowrelay.it/api/v1/integrations" \
-H "Authorization: Bearer fr_your_api_key"Response
{
"integrations": [
{
"source": "github",
"workspace_id": "acme",
"workspace_name": "Acme",
"connected_at": "2026-05-01T09:00:00Z",
"scope": "project",
"resource_type": "repository",
"connection_status": "active",
"providers_connected": 2,
"last_validated_at": "2026-06-20T10:00:00Z"
}
]
}| Status | When |
|---|---|
| 200 | Success |
| 401 | Missing or invalid API key. |
| 404 | Project not found or not accessible by this key. |
List untracked resources
/integrations/untrackedReturns active resources (last 30 days) that produced events but are not yet assigned to any project. The response is a bare array, sorted by most recent activity.
Request
curl "https://www.flowrelay.it/api/v1/integrations/untracked" \
-H "Authorization: Bearer fr_your_api_key"Response
[
{
"source": "slack",
"resource_id": "C0123",
"resource_name": "#incidents",
"resource_type": "channel",
"event_count": 42,
"last_event_at": "2026-06-20T12:00:00Z"
}
]| Status | When |
|---|---|
| 200 | Success |
| 401 | Missing or invalid API key. |
| 500 | Discovery failed for a connected source. |
Poll an async job
/jobs/{jobId}Returns the job record and, once completed, the generated artifact (handoff or insight). Poll this after any 202 response until status is completed or failed.
Path parameters
| Name | Type | Description |
|---|---|---|
jobIdrequired | string | Job id from a 202 response. |
Request
curl "https://www.flowrelay.it/api/v1/jobs/JOB_ID" \
-H "Authorization: Bearer fr_your_api_key"Response
{
"job": {
"id": "job_9f3c",
"project_id": "proj_8c1d",
"kind": "project_handoff",
"status": "completed",
"result_kind": "handoff",
"result_id": "ho_1a2b",
"error": null,
"error_code": null,
"created_at": "2026-06-20T14:02:00Z",
"updated_at": "2026-06-20T14:03:00Z"
},
"result": {
"id": "ho_1a2b",
"title": "Checkout refactor handoff"
}
}| Status | When |
|---|---|
| 200 | Success |
| 401 | Missing or invalid API key. |
| 404 | Job not found or not accessible. |
List Discord channels
/discord/channelsLists the text channels in the Discord guild connected to the key owner.
Request
curl "https://www.flowrelay.it/api/v1/discord/channels" \
-H "Authorization: Bearer fr_your_api_key"Response
{
"channels": [
{
"id": "987654",
"name": "general",
"type": 0
}
]
}| Status | When |
|---|---|
| 200 | Success |
| 401 | Missing or invalid API key. |
| 404 | Discord not connected. |
| 400 | No guild associated with this integration. |
Send a Discord message
/discord/sendSends a message to a channel in the connected guild. The channel must belong to that guild (cross-tenant posts are rejected).
Body parameters
| Name | Type | Description |
|---|---|---|
channel_idrequired | string | Target channel id. |
contentrequired | string | Message text. |
Request
curl "https://www.flowrelay.it/api/v1/discord/send" \
-H "Authorization: Bearer fr_your_api_key" \
-X POST \
-H "Content-Type: application/json" \
-d '{ "channel_id": "987654", "content": "Handoff ready" }'Request body
{
"channel_id": "987654",
"content": "Handoff ready"
}Response
{
"ok": true,
"message_id": "111222333"
}| Status | When |
|---|---|
| 200 | Success |
| 400 | channel_id and content are required. |
| 401 | Missing or invalid API key. |
| 403 | Channel does not belong to the connected guild. |
| 404 | Discord not connected. |