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.

Import openapi.json into Postman or Insomnia to generate a client.

Finding IDs

Every id is a UUID you discover from a list endpoint – you never need to know one up front.

You needGet it from
project_id (and {id} in the path)GET /projects
handoff_idGET /handoffs
insight_idGET /projects/{id}/insights
digest_idGET /projects/{id}/digests
channel_idGET /discord/channels
filter values (repos, branches, etc.)GET /handoffs/filters?project_id=...
jobIdreturned in the 202 response when you start a generation
work item ref (key such as FR-12, or id)GET /projects/{id}/work-items or GET /my-work
importIdreturned by POST /projects/{id}/imports, or GET /projects/{id}/imports
suggestionIdGET /projects/{id}/suggestions

List accessible projects

GET/projects

Returns the tenant context for the key owner: account type, organization memberships and every personal or organization project the key can access (role-scoped). `key` is the prefix of the work item keys of the project (`PAY` in `PAY-12`).

Request

curl "https://www.flowrelay.it/api/v1/projects" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "account_type": "business",
  "organizations": [
    {
      "id": "8c2b1a90-1234-4abc-9def-0123456789ab",
      "name": "Acme",
      "slug": "acme",
      "role": "admin",
      "is_temporary_admin": false
    }
  ],
  "projects": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "Payments",
      "slug": "payments",
      "key": "PAY",
      "description": "Billing and checkout",
      "organization_id": "8c2b1a90-1234-4abc-9def-0123456789ab",
      "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"
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
429Rate limit exceeded (60/min/key).

List handoffs

GET/handoffs

Lists handoffs across accessible projects, newest first. Without project_id it spans every project the key can access.

Query parameters

NameTypeDescription
statusoptionalstringFilter by status.One of: active, archived, allDefault: active
limitoptionalintegerMaximum rows to return (1–100).Default: 20
project_idoptionalstringRestrict to a single project.

Request

curl "https://www.flowrelay.it/api/v1/handoffs" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "handoffs": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "kind": "project",
      "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"
      ],
      "completion_percentage": null,
      "related_event_ids": [
        "d4e5f6a7-b8c9-0123-def4-23456789013a"
      ],
      "scope_type": "project",
      "project_name": "Payments",
      "created_at": "2026-06-20T14:03:00Z",
      "updated_at": "2026-06-20T14:03:00Z",
      "markdown": "# Checkout refactor handoff\n\n> Migrated the checkout flow…"
    }
  ]
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
404Project not found or not accessible by this key.

Generate a handoff

POST/handoffs

Asynchronous – 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

NameTypeDescription
project_idrequiredstringProject UUID to generate the handoff for (from GET /projects).
sourcesoptionalstring[]Restrict generation to these sources. Each must be a known source id; an unknown value is rejected with 400 (not silently ignored). Omit to use every connected source.One of: github, slack, discord, linear, notion, jira, gitlab, bitbucket, azure_devops, figma, confluence, microsoft_outlook, microsoft_teams, sentry, datadog, pagerduty, asana, gmail, buildkite, circleci, vercel, incident_io, netlify, render, railway, cloudflare_pages, clickup, monday_com, shortcut, intercom, zendesk, snyk, fireflies, zoom, grafana, google_calendar, google_drive, launchdarkly, hcp_terraform, sonarqube, miro, new_relic, jira_service_management, posthog, hubspot, salesforce, heroku, alertmanager, pulumi, google_meet, microsoft_teams_meetings, fathom
filtersoptionalSourceFilterPer-source projects / eventTypes / branches / priorities (AND-combined). Keys must be source ids (unknown keys are rejected with 400); the values are provider-driven and matched leniently – an unmatched value simply returns no events. Fetch GET /handoffs/filters for the set selectable on a project.

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": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "sources": [ "github", "linear" ], "filters": { "github": { "branches": [ "main" ] } } }'

Request body

JSON
{
  "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "sources": [
    "github",
    "linear"
  ],
  "filters": {
    "github": {
      "branches": [
        "main"
      ]
    }
  }
}

Response

JSON
{
  "jobId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "status": "pending"
}
StatusWhen
202Job enqueued. Poll GET /jobs/{jobId} for the result.
400project_id is missing or invalid, or the body failed validation (unknown field / source / filter value). The response names the field and lists allowed values.
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

List selectable filter options

GET/handoffs/filters

Returns the real selectable filter values per connected source for a project: resources (repos / channels / boards / Figma files), branches, event types, and priorities. Use these to build a valid SourceFilter instead of guessing. The response also carries a "figma" availability block: Figma can be selected only on projects in the Global processing region, and selecting it attaches visual context (frame renders) at a flat 1-credit surcharge.

Query parameters

NameTypeDescription
project_idrequiredstringProject UUID (from GET /projects) 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

JSON
{
  "filters": {
    "github": {
      "projects": [
        {
          "id": "acme/payments",
          "label": "acme/payments"
        }
      ],
      "eventTypes": [
        {
          "value": "push",
          "label": "Push"
        }
      ],
      "priorities": [],
      "branches": [
        {
          "value": "main",
          "label": "main"
        }
      ]
    },
    "linear": {
      "projects": [
        {
          "id": "f1e2d3c4-b5a6-7890-1234-567890abcdef",
          "label": "Core"
        }
      ],
      "eventTypes": [
        {
          "value": "issue",
          "label": "Issue"
        }
      ],
      "priorities": [
        {
          "value": "high",
          "label": "High"
        }
      ]
    }
  },
  "figma": {
    "selectable": true,
    "region": "default",
    "scope": "personal",
    "canManageResidency": true,
    "residencyHref": "/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6#data-residency"
  }
}
StatusWhen
200Success
400project_id is missing or not a valid UUID.
401Missing or invalid API key.
404Project not found or not accessible by this key.

List project insights

GET/projects/{id}/insights

Lists AI insights for a project, newest first. Release notes and plan reviews are stored as insights too, so they show up here alongside the three analysis kinds. Optionally filter by kind and status.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Query parameters

NameTypeDescription
kindoptionalstringFilter by insight kind.One of: cross_source_correlation, onboarding_brief, architecture_insight, release_notes, plan_review
statusoptionalstringFilter by status.One of: active, archived, allDefault: active
limitoptionalintegerMaximum rows to return (1–100).Default: 20

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/insights" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "insights": [
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "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-3.8-flash",
      "status": "active",
      "related_event_ids": [
        "d4e5f6a7-b8c9-0123-def4-23456789013a"
      ],
      "sources": [
        "github"
      ],
      "created_at": "2026-06-21T08:00:00Z",
      "updated_at": "2026-06-21T08:00:00Z",
      "markdown": "# Pricing engine trade-offs\n\n> Flat per-artifact pricing…"
    }
  ]
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
404Project not found or not accessible by this key.

Generate an insight

POST/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

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
kindrequiredstringInsight kind. `plan_review` writes a status report from the numbers of the plan (5 credits) and needs a project role that can write.One of: correlation, onboarding, architecture, release_notes, plan_review

Body parameters

NameTypeDescription
lookbackHoursoptionalintegercorrelation only – window in hours (1–2160, default 168). Rejected on other kinds.
lookbackDaysoptionalintegeronboarding / architecture – window in days (1–365, default 30 / 14). Rejected on correlation and on release_notes, which always covers the last 14 days.
newMemberRoleoptionalstringonboarding only – role of the person being onboarded.
focusAreaoptionalstringonboarding only – area to emphasise.
focusQuestionoptionalstringarchitecture only – the question to investigate.
sourceoptionalstringrelease_notes only – the code source to read (default github).One of: github, gitlab, bitbucket, azure_devops
repooptionalstringrelease_notes only – restrict to one repository, matched against the events' repository name. Defaults to every repository the project tracks.
styleoptionalstringrelease_notes only – output shape (default release_notes).One of: release_notes, pr_description
sourcesoptionalstring[]Restrict to these sources. Unknown values are rejected with 400. On release_notes it widens the scope past the code source named by `source` (a build source alongside the repository, say); omit it to read that source alone.One of: github, slack, discord, linear, notion, jira, gitlab, bitbucket, azure_devops, figma, confluence, microsoft_outlook, microsoft_teams, sentry, datadog, pagerduty, asana, gmail, buildkite, circleci, vercel, incident_io, netlify, render, railway, cloudflare_pages, clickup, monday_com, shortcut, intercom, zendesk, snyk, fireflies, zoom, grafana, google_calendar, google_drive, launchdarkly, hcp_terraform, sonarqube, miro, new_relic, jira_service_management, posthog, hubspot, salesforce, heroku, alertmanager, pulumi, google_meet, microsoft_teams_meetings, fathom
filtersoptionalSourceFilterPer-source filters (AND-combined). Keys must be source ids (unknown keys are rejected with 400); values are matched leniently (see GET /handoffs/filters).
maxEventsoptionalintegerCap the events fed to the model (1–1000). Rejected on release_notes.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/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

JSON
{
  "focusQuestion": "Is the pricing engine coupling billing to providers?",
  "lookbackDays": 14
}

Response

JSON
{
  "jobId": "e7f8a9b0-1c2d-3e4f-5a6b-7c8d9e0f1a2b",
  "status": "pending"
}
StatusWhen
202Job enqueued. Poll GET /jobs/{jobId} for the result.
400Unsupported insight kind, or the body failed validation (unknown field / source / filter value, or a field that does not apply to this kind). The response names the field and lists allowed values.
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Ask a question about a project

POST/projects/{id}/qa

Answers one question grounded in the project context: the indexed codebase, connected baselines and the last 14 days of scoped activity. Synchronous – the answer comes back in the response, there is no job to poll. The answer cites the events it relied on as `ev:` plus the first 8 characters of the event id. Costs 2 credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Body parameters

NameTypeDescription
questionrequiredstringThe question, 1 to 2000 characters.
filtersoptionalSourceFilterPer-source filters (AND-combined) narrowing the activity considered.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/qa" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "question": "Why did we move checkout off the legacy queue?" }'

Request body

JSON
{
  "question": "Why did we move checkout off the legacy queue?"
}

Response

JSON
{
  "answer": "Checkout moved off the legacy queue because the retry semantics could double-charge on a partial failure…",
  "citations": [
    "ev:a1b2c3d4",
    "ev:9f8e7d6c"
  ]
}
StatusWhen
200Answer produced.
400question missing, empty, longer than 2000 characters, or an unknown body field was sent.
401Missing or invalid API key.
402The plan does not allow this flow.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).
504The answer took longer than 60s. Narrow the question.

List context events

GET/events

Lists 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

NameTypeDescription
sourceoptionalstringFilter by source. Unknown values are rejected with 400.One of: github, slack, discord, linear, notion, jira, gitlab, bitbucket, azure_devops, figma, confluence, microsoft_outlook, microsoft_teams, sentry, datadog, pagerduty, asana, gmail, buildkite, circleci, vercel, incident_io, netlify, render, railway, cloudflare_pages, clickup, monday_com, shortcut, intercom, zendesk, snyk, fireflies, zoom, grafana, google_calendar, google_drive, launchdarkly, hcp_terraform, sonarqube, miro, new_relic, jira_service_management, posthog, hubspot, salesforce, heroku, alertmanager, pulumi, google_meet, microsoft_teams_meetings, fathom
limitoptionalintegerMaximum rows to return (1–200).Default: 50
project_idoptionalstringRestrict to a project scope.

Request

curl "https://www.flowrelay.it/api/v1/events" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "events": [
    {
      "id": "d4e5f6a7-b8c9-0123-def4-23456789013a",
      "user_id": "0a9b8c7d-6e5f-4a3b-2c1d-0e9f8a7b6c5d",
      "source": "github",
      "event_type": "push",
      "title": "Push to acme/payments",
      "content": "3 commits on main",
      "created_at": "2026-06-20T13:55:00Z"
    }
  ]
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
404Project not found or not accessible by this key.

List integrations

GET/integrations

Lists 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

NameTypeDescription
project_idoptionalstringReturn project-scoped integrations instead of personal ones.

Request

curl "https://www.flowrelay.it/api/v1/integrations" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "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"
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
404Project not found or not accessible by this key.

List untracked resources

GET/integrations/untracked

Returns 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

JSON
[
  {
    "source": "slack",
    "resource_id": "C0123",
    "resource_name": "#incidents",
    "resource_type": "channel",
    "event_count": 42,
    "last_event_at": "2026-06-20T12:00:00Z"
  }
]
StatusWhen
200Success
401Missing or invalid API key.
500Discovery failed for a connected source.

Poll an async job

GET/jobs/{jobId}

Returns the job record and, once completed, the generated artifact. `kind` names the generation (`project_handoff`, `cross_source_correlation`, `onboarding_brief`, `architecture_insight`, `release_notes`, `project_digest`) and `result_kind` tells you where the artifact lives (`handoff`, `insight` – release notes included – or `digest`). The artifact carries a `markdown` field with the canonical rendering – identical to the dashboard copy button. Poll this after any 202 response until status is completed or failed. While the job runs, `progress.phase` reports the stage the worker actually reached (`loading_context`, `retrieving`, `generating`, `saving`); it is null until the first phase is written.

Path parameters

NameTypeDescription
jobIdrequiredstringUUID of the job returned in a prior 202 (POST /handoffs or POST /projects/{id}/insights/{kind}). Project-scoped: only readable if you can access the job's project.

Request

curl "https://www.flowrelay.it/api/v1/jobs/c3d4e5f6-a7b8-9012-cdef-123456789012" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "job": {
    "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
    "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "kind": "project_handoff",
    "status": "completed",
    "result_kind": "handoff",
    "result_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "error": null,
    "error_code": null,
    "progress": {
      "phase": "saving",
      "at": "2026-06-20T14:02:55Z"
    },
    "created_at": "2026-06-20T14:02:00Z",
    "updated_at": "2026-06-20T14:03:00Z"
  },
  "result": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "title": "Checkout refactor handoff",
    "markdown": "# Checkout refactor handoff\n\n> Migrated the checkout flow…"
  }
}
StatusWhen
200Success
400jobId is not a valid UUID.
401Missing or invalid API key.
404Job not found or not accessible.

List Discord channels

GET/discord/channels

Lists 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

JSON
{
  "channels": [
    {
      "id": "987654",
      "name": "general",
      "type": 0
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
404Discord not connected.
400No guild associated with this integration.

Send a Discord message

POST/discord/send

Sends to a channel in the connected guild. Provide exactly one of: content (inline text); handoff_id or insight_id (renders that artifact to Markdown and attaches it as a .md file); or artifact (last_handoff / last_correlation / last_onboarding / last_architecture / last_release_notes, with project_id) to send the latest active artifact of that kind. Rendered artifacts use the same Markdown as the dashboard copy button and are always delivered as a .md attachment. The channel must belong to the connected guild (cross-tenant posts are rejected).

Body parameters

NameTypeDescription
channel_idrequiredstringTarget channel id – a Discord snowflake from GET /discord/channels.
contentoptionalstringInline message text. Mutually exclusive with handoff_id / insight_id / artifact.
handoff_idoptionalstringUUID of a handoff (from GET /handoffs). Rendered to Markdown and sent as a .md attachment.
insight_idoptionalstringUUID of an insight (from GET /projects/{id}/insights). Sent as a .md attachment.
artifactoptionalstringSend the latest active artifact of a kind. Requires project_id.One of: last_handoff, last_correlation, last_onboarding, last_architecture, last_release_notes
project_idoptionalstringProject UUID. Required only when artifact is set.

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": "987654321098765432", "artifact": "last_handoff", "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }'

Request body

JSON
{
  "channel_id": "987654321098765432",
  "artifact": "last_handoff",
  "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

Response

JSON
{
  "ok": true,
  "message_id": "111222333444555666"
}
StatusWhen
200Success
400channel_id missing, or no content / artifact provided.
401Missing or invalid API key.
403Channel does not belong to the connected guild.
404Discord not connected, or the requested artifact does not exist / is not accessible.
502Discord rejected the message.

List my work

GET/my-work

Lists the work items assigned to the key owner across every accessible project: open items plus the ones finished in the last 7 days. Dates are wall-clock times in the time zone of each item project, named on the project.

Request

curl "https://www.flowrelay.it/api/v1/my-work" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "items": [
    {
      "id": "4b8e2f1a-9c3d-4e5f-8a7b-6c5d4e3f2a10",
      "key": "FR-12",
      "title": "Move invoices to Paddle",
      "status": "in_progress",
      "blocked": false,
      "priority": 3,
      "kind": "task",
      "percentComplete": 40,
      "start": "2026-09-28T08:00",
      "finish": "2026-10-02T17:00",
      "deadline": "2026-10-09T17:00",
      "updatedAt": "2026-09-28T09:14:03Z",
      "url": "https://www.flowrelay.it/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work?item=FR-12",
      "project": {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "name": "Billing",
        "timezone": "Europe/Rome"
      }
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
429Rate limit exceeded (60/min/key).

List work items

GET/projects/{id}/work-items

Lists the tasks and milestones of a project plan ordered by item number, with the dates computed by the scheduler. Dates are wall-clock times (`YYYY-MM-DDTHH:mm`) in the plan time zone returned as `timezone`. Pass `nextCursor` back as `cursor` to read the next page.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Query parameters

NameTypeDescription
statusoptionalstringComma-separated statuses to keep (for example `todo,in_progress`). Omit for every status.One of: backlog, todo, in_progress, in_review, done, cancelled
assigneeoptionalstringOnly `me` is accepted: the items assigned to the key owner.One of: me
limitoptionalintegerItems per page (1-200, default 100).Default: 100
cursoroptionalintegerThe `nextCursor` of the previous page.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work-items" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "timezone": "Europe/Rome",
  "items": [
    {
      "id": "4b8e2f1a-9c3d-4e5f-8a7b-6c5d4e3f2a10",
      "key": "FR-12",
      "number": 12,
      "title": "Move invoices to Paddle",
      "kind": "task",
      "status": "in_progress",
      "blocked": false,
      "priority": 3,
      "isSummary": false,
      "parentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
      "percentComplete": 40,
      "start": "2026-09-28T08:00",
      "finish": "2026-10-02T17:00",
      "deadline": "2026-10-09T17:00",
      "durationMinutes": 2400,
      "critical": true,
      "assignees": [
        {
          "userId": "0a9b8c7d-6e5f-4a3b-2c1d-0e9f8a7b6c5d",
          "name": "Ada Rossi"
        }
      ],
      "version": 57,
      "updatedAt": "2026-09-28T09:14:03Z",
      "url": "https://www.flowrelay.it/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work?item=FR-12"
    }
  ],
  "nextCursor": 12
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Create a work item

POST/projects/{id}/work-items

Creates a task or milestone and schedules it. The item gets the next number of the project and a key such as `FR-12`. Contributors can create items when the project allows it and can assign only themselves. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Body parameters

NameTypeDescription
titlerequiredstringTitle, 1 to 500 characters.
descriptionoptionalstringPlain text or Markdown, up to 50000 characters.
parentoptionalstringKey or id of the parent item to nest under.
kindoptionalstringTask or milestone.One of: task, milestoneDefault: task
statusoptionalstringInitial status.One of: backlog, todo, in_progress, in_review, done, cancelledDefault: todo
priorityoptionalinteger0 lowest to 4 urgent.Default: 2
durationoptionalstringWorking duration such as `4h`, `3d` or `2w` (the plan decides how long a day is), `3ed` for elapsed days, a trailing `?` for an estimate.
deadlineoptionalstring`YYYY-MM-DD` or `YYYY-MM-DDTHH:mm` in the plan time zone.
assigneeoptionalstring`me`, or the user id of a project member (managers only).

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work-items" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "title": "Move invoices to Paddle", "parent": "FR-3", "duration": "3d", "deadline": "2026-10-09", "assignee": "me" }'

Request body

JSON
{
  "title": "Move invoices to Paddle",
  "parent": "FR-3",
  "duration": "3d",
  "deadline": "2026-10-09",
  "assignee": "me"
}

Response

JSON
{
  "item": {
    "id": "4b8e2f1a-9c3d-4e5f-8a7b-6c5d4e3f2a10",
    "key": "FR-12",
    "number": 12,
    "title": "Move invoices to Paddle",
    "kind": "task",
    "status": "in_progress",
    "blocked": false,
    "priority": 3,
    "isSummary": false,
    "parentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
    "percentComplete": 40,
    "start": "2026-09-28T08:00",
    "finish": "2026-10-02T17:00",
    "deadline": "2026-10-09T17:00",
    "durationMinutes": 2400,
    "critical": true,
    "assignees": [
      {
        "userId": "0a9b8c7d-6e5f-4a3b-2c1d-0e9f8a7b6c5d",
        "name": "Ada Rossi"
      }
    ],
    "version": 57,
    "updatedAt": "2026-09-28T09:14:03Z",
    "url": "https://www.flowrelay.it/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work?item=FR-12",
    "description": "Replace the legacy invoice job with Paddle transactions.",
    "predecessors": [
      {
        "key": "FR-3",
        "type": "fs",
        "lagMinutes": 0
      }
    ],
    "successors": [
      {
        "key": "FR-15",
        "type": "fs",
        "lagMinutes": 0
      }
    ],
    "evidence": [
      {
        "source": "github",
        "kind": "commit",
        "title": "FR-12 switch invoice webhook to Paddle",
        "url": "https://github.com/acme/billing/commit/4f2a9c1",
        "occurredAt": "2026-09-28T08:42:11Z"
      }
    ],
    "commentCount": 2
  },
  "warnings": []
}
StatusWhen
201Item created and scheduled.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Work management is not part of the plan, or the project reached its item limit.
403The project role of the key owner cannot create items or assign other people.
404Project or parent item not found or not accessible by this key.
409The plan kept changing while the item was saved. Retry.
429Rate limit exceeded (60/min/key).

Get a work item

GET/projects/{id}/work-items/{ref}

Returns one work item by key or id with its description, scheduled dates, assignees, dependencies, the ten most recent accepted evidence links and the comment count.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
refrequiredstringItem key such as `FR-12`, or the item id.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work-items/FR-12" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "timezone": "Europe/Rome",
  "item": {
    "id": "4b8e2f1a-9c3d-4e5f-8a7b-6c5d4e3f2a10",
    "key": "FR-12",
    "number": 12,
    "title": "Move invoices to Paddle",
    "kind": "task",
    "status": "in_progress",
    "blocked": false,
    "priority": 3,
    "isSummary": false,
    "parentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
    "percentComplete": 40,
    "start": "2026-09-28T08:00",
    "finish": "2026-10-02T17:00",
    "deadline": "2026-10-09T17:00",
    "durationMinutes": 2400,
    "critical": true,
    "assignees": [
      {
        "userId": "0a9b8c7d-6e5f-4a3b-2c1d-0e9f8a7b6c5d",
        "name": "Ada Rossi"
      }
    ],
    "version": 57,
    "updatedAt": "2026-09-28T09:14:03Z",
    "url": "https://www.flowrelay.it/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work?item=FR-12",
    "description": "Replace the legacy invoice job with Paddle transactions.",
    "predecessors": [
      {
        "key": "FR-3",
        "type": "fs",
        "lagMinutes": 0
      }
    ],
    "successors": [
      {
        "key": "FR-15",
        "type": "fs",
        "lagMinutes": 0
      }
    ],
    "evidence": [
      {
        "source": "github",
        "kind": "commit",
        "title": "FR-12 switch invoice webhook to Paddle",
        "url": "https://github.com/acme/billing/commit/4f2a9c1",
        "occurredAt": "2026-09-28T08:42:11Z"
      }
    ],
    "commentCount": 2
  }
}
StatusWhen
200Success
401Missing or invalid API key.
404Project or item not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Update a work item

PATCH/projects/{id}/work-items/{ref}

Changes the fields you send and reschedules the plan. Sending the same values again leaves the item unchanged. Contributors can update the items assigned to them or created by them; dates and durations may need a project manager. Pass `ifVersion` (the `version` you read) to refuse the change when someone edited the item in the meantime. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
refrequiredstringItem key such as `FR-12`, or the item id.

Body parameters

NameTypeDescription
statusoptionalstringNew status. `done` sets progress to 100.One of: backlog, todo, in_progress, in_review, done, cancelled
percentCompleteoptionalintegerProgress 0 to 100. 100 marks the item done.
titleoptionalstringTitle, 1 to 500 characters.
descriptionoptionalstringPlain text or Markdown, up to 50000 characters.
priorityoptionalinteger0 lowest to 4 urgent.
blockedoptionalbooleanFlag or unflag the item as blocked. A flag, not a status.
durationoptionalstringWorking duration such as `4h`, `3d` or `2w`.
deadlineoptionalstring`YYYY-MM-DD` or `YYYY-MM-DDTHH:mm` in the plan time zone, or null to clear it.
ifVersionoptionalintegerApply only if the item still has this `version`.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work-items/FR-12" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X PATCH \
  -H "Content-Type: application/json" \
  -d '{ "status": "done", "ifVersion": 57 }'

Request body

JSON
{
  "status": "done",
  "ifVersion": 57
}

Response

JSON
{
  "item": {
    "id": "4b8e2f1a-9c3d-4e5f-8a7b-6c5d4e3f2a10",
    "key": "FR-12",
    "number": 12,
    "title": "Move invoices to Paddle",
    "kind": "task",
    "status": "done",
    "blocked": false,
    "priority": 3,
    "isSummary": false,
    "parentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
    "percentComplete": 100,
    "start": "2026-09-28T08:00",
    "finish": "2026-10-02T17:00",
    "deadline": "2026-10-09T17:00",
    "durationMinutes": 2400,
    "critical": true,
    "assignees": [
      {
        "userId": "0a9b8c7d-6e5f-4a3b-2c1d-0e9f8a7b6c5d",
        "name": "Ada Rossi"
      }
    ],
    "version": 58,
    "updatedAt": "2026-09-28T09:14:03Z",
    "url": "https://www.flowrelay.it/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work?item=FR-12",
    "description": "Replace the legacy invoice job with Paddle transactions.",
    "predecessors": [
      {
        "key": "FR-3",
        "type": "fs",
        "lagMinutes": 0
      }
    ],
    "successors": [
      {
        "key": "FR-15",
        "type": "fs",
        "lagMinutes": 0
      }
    ],
    "evidence": [
      {
        "source": "github",
        "kind": "commit",
        "title": "FR-12 switch invoice webhook to Paddle",
        "url": "https://github.com/acme/billing/commit/4f2a9c1",
        "occurredAt": "2026-09-28T08:42:11Z"
      }
    ],
    "commentCount": 2
  },
  "warnings": []
}
StatusWhen
200Item updated and the plan rescheduled.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Work management is not part of the plan.
403The project role of the key owner cannot change these fields on this item.
404Project or item not found or not accessible by this key.
409`ifVersion` no longer matches: the item changed since you read it.
422The plan cannot be scheduled with this change (no working time left on the calendar).
429Rate limit exceeded (60/min/key).

Delete a work item

DELETE/projects/{id}/work-items/{ref}

Soft-deletes the item and its sub-items, removes their dependencies and assignments from the plan and reschedules it. The deletion is recorded as one batch in the change history, so a project manager can restore it. Contributors can delete only the items they created. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
refrequiredstringItem key such as `FR-12`, or the item id.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work-items/FR-12" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X DELETE

Response

Returns 204 with no body.

StatusWhen
204Item deleted and the plan rescheduled.
401Missing or invalid API key.
402Work management is not part of the plan.
403The project role of the key owner cannot delete this item.
404Project or item not found or not accessible by this key.
422The plan cannot be scheduled after the change.
429Rate limit exceeded (60/min/key).

List the evidence of a work item

GET/projects/{id}/work-items/{ref}/evidence

Returns the activity linked to one work item, newest first: accepted evidence (commits, pull requests, builds, deploys, incidents, meetings, documents and manual links) plus the suggested evidence routed to the key owner. Project owners and managers also see the suggestions that name no author. `author` is a name only when the activity is attributed through a confirmed linked account and the organization allows named authors, otherwise null. `ref` also accepts a former project key and the key a tracker gave a mirrored item.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
refrequiredstringItem key such as `FR-12`, the tracker key of a mirrored item such as `PAY-123`, or the item id.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work-items/FR-12/evidence" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "evidence": [
    {
      "id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b",
      "source": "github",
      "kind": "pull_request",
      "reference": "acme/billing#41",
      "url": "https://github.com/acme/billing/pull/41",
      "title": "FR-12 switch invoice webhook",
      "occurredAt": "2026-09-28T08:30:00Z",
      "origin": "key_reference",
      "status": "accepted",
      "confidence": 1,
      "author": "Ada Rossi"
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
404Project or item not found or not accessible by this key.
429Rate limit exceeded (60/min/key).
POST/projects/{id}/work-items/{ref}/evidence

Attaches an https link (a pull request, commit, build, deploy, incident, document or anything else) to a work item as accepted evidence. It joins the activity trail of the item and its evidence coverage. Sending the same link again updates its title, kind and time and creates no duplicate. Viewers cannot link. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
refrequiredstringItem key such as `FR-12`, or the item id.

Body parameters

NameTypeDescription
urlrequiredstringThe https link, up to 500 characters.
titleoptionalstringTitle, 1 to 300 characters. Defaults to the link itself.
kindoptionalstringWhat the link points to.One of: commit, branch, pull_request, review, build, deploy, incident, ticket, message, meeting, document, otherDefault: other
occurredAtoptionalstringWhen the work happened, ISO 8601. Defaults to now.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/work-items/FR-12/evidence" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://github.com/acme/billing/pull/41", "kind": "pull_request", "occurredAt": "2026-09-28T08:30:00Z" }'

Request body

JSON
{
  "url": "https://github.com/acme/billing/pull/41",
  "kind": "pull_request",
  "occurredAt": "2026-09-28T08:30:00Z"
}

Response

JSON
{
  "linked": true,
  "url": "https://github.com/acme/billing/pull/41"
}
StatusWhen
201Link attached.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Work management is not part of the plan.
403The key owner is a viewer of this project.
404Project or item not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

List pending suggestions

GET/projects/{id}/suggestions

Returns the pending suggestions of a plan that the key owner can act on: `status_change` (a status proposed from linked activity, first offered to the assignee and shown to managers after three working days), `create_item` (an action item from a meeting transcript), `dependency` (a blocking link found in a mirrored tracker) and `evidence` (activity that looks related to an item). `forYou` marks the ones routed to the key owner. Nothing changes until a suggestion is accepted.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/suggestions" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "suggestions": [
    {
      "id": "0f3e1d2c-4b5a-4987-8a6b-5c4d3e2f1a09",
      "type": "status_change",
      "item": "FR-12",
      "payload": {
        "from": "in_progress",
        "to": "in_review",
        "reason": "Pull request opened: acme/billing#41"
      },
      "origin": "evidence_rule",
      "forYou": true,
      "createdAt": "2026-09-28T10:00:00Z"
    },
    {
      "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "type": "create_item",
      "item": null,
      "payload": {
        "title": "Send the revised invoice template to finance",
        "description": null,
        "parent": null,
        "reason": "From the meeting \"Billing sync\" of 2026-09-27"
      },
      "origin": "meeting",
      "forYou": false,
      "createdAt": "2026-09-27T16:10:00Z"
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Accept or dismiss a suggestion

POST/projects/{id}/suggestions/{suggestionId}

`accept` applies the suggestion with the permissions of the key owner: the status change, the new item, the dependency or the evidence link. `dismiss` closes it. A status change whose item moved on in the meantime expires instead of overwriting the newer status. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
suggestionIdrequiredstringSuggestion UUID (from GET /projects/{id}/suggestions).

Body parameters

NameTypeDescription
actionrequiredstringWhat to do with the suggestion.One of: accept, dismiss

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/suggestions/0f3e1d2c-4b5a-4987-8a6b-5c4d3e2f1a09" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "action": "accept" }'

Request body

JSON
{
  "action": "accept"
}

Response

JSON
{
  "status": "accepted",
  "numbers": {},
  "version": 58
}
StatusWhen
200Accepted or dismissed.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
403The project role of the key owner cannot make this change.
404Project or suggestion not found, or the suggestion is not visible to this key.
409The suggestion was already decided, or the item changed since it was made.
422The suggestion no longer describes a change that can be applied.
429Rate limit exceeded (60/min/key).

Start a plan import

POST/projects/{id}/imports

Starts importing an MS Project XML file (MSPDI, from Project desktop Save As > XML), an Oracle Primavera P6 file (.xer), or a CSV file and returns a signed upload URL. Upload the file with `PUT` to `upload.signedUrl` within 2 hours, sending `Content-Type: application/xml`, `text/plain` or `text/csv` and no Authorization header (50 MB at most), then call `POST /projects/{id}/imports/{importId}` with `{"action": "parse"}`. Project managers only. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Body parameters

NameTypeDescription
kindrequiredstring`mspdi` for an MS Project XML file, `xer` for an Oracle Primavera P6 export, `csv` for a spreadsheet export.One of: mspdi, csv, xer
fileNamerequiredstringName of the file, up to 255 characters. Shown in the import history.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/imports" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "kind": "mspdi", "fileName": "launch-plan.xml" }'

Request body

JSON
{
  "kind": "mspdi",
  "fileName": "launch-plan.xml"
}

Response

JSON
{
  "importId": "6d1f0c2a-8b3e-4f5a-9c7d-2e1f0a9b8c7d",
  "upload": {
    "bucket": "plan-imports",
    "path": "3fa85f64-5717-4562-b3fc-2c963f66afa6/6d1f0c2a-8b3e-4f5a-9c7d-2e1f0a9b8c7d/launch-plan.xml",
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJwbGFuLWltcG9ydHMvLi4uIn0.signature",
    "signedUrl": "https://xyzcompany.supabase.co/storage/v1/object/upload/sign/plan-imports/3fa85f64-5717-4562-b3fc-2c963f66afa6/6d1f0c2a-8b3e-4f5a-9c7d-2e1f0a9b8c7d/launch-plan.xml?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJwbGFuLWltcG9ydHMvLi4uIn0.signature"
  }
}
StatusWhen
201Import created. Upload the file to `upload.signedUrl`.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Importing plans is not part of the plan (Starter and above).
403The key owner is not a manager of this project.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key, and 10 imports per hour per user).

List plan imports

GET/projects/{id}/imports

Lists the ten most recent imports of a project, newest first, with their status, preview, warnings and results.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/imports" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "imports": [
    {
      "id": "6d1f0c2a-8b3e-4f5a-9c7d-2e1f0a9b8c7d",
      "kind": "mspdi",
      "status": "preview",
      "file_name": "launch-plan.xml",
      "preview": {
        "name": "Launch plan",
        "counts": {
          "tasks": 312,
          "summaries": 41,
          "milestones": 9,
          "links": 356,
          "assignments": 288,
          "calendars": 2
        },
        "baselines": [
          0
        ],
        "customFields": [
          {
            "key": "workstream",
            "label": "Workstream",
            "type": "text"
          }
        ],
        "resources": [
          {
            "ref": "3",
            "name": "Ada Rossi",
            "email": "ada@acme.dev",
            "suggested": "f3a2b1c0-9d8e-4f7a-8b6c-5d4e3f2a1b0c"
          },
          {
            "ref": "7",
            "name": "Contractor",
            "email": null,
            "suggested": null
          }
        ],
        "settings": {
          "projectStart": "2026-10-05T08:00",
          "statusDate": null,
          "minutesPerDay": 480,
          "minutesPerWeek": 2400,
          "daysPerMonth": 20,
          "calendar": "Standard"
        },
        "sample": [
          {
            "ref": "1",
            "level": 1,
            "name": "Discovery",
            "durationMinutes": 4800,
            "start": "2026-10-05T08:00",
            "finish": "2026-10-16T17:00"
          }
        ],
        "existingItems": 0,
        "csv": null
      },
      "warnings": [
        {
          "code": "split_task",
          "message": "2 split tasks were imported as one continuous bar.",
          "refs": [
            "58",
            "61"
          ]
        }
      ],
      "stats": {},
      "error": null,
      "created_at": "2026-09-28T09:20:11Z",
      "applied_at": null
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Get a plan import

GET/projects/{id}/imports/{importId}

Returns one import. `status` moves from `uploading` to `parsing`, then `preview` (read the counts, the resources to map and the `warnings`) and, after `apply`, to `applying` and `applied` with the results in `stats`. `failed` carries the reason in `error`. The `preview` is dropped once the import is applied or discarded. Poll every few seconds while it is `parsing` or `applying`.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
importIdrequiredstringImport UUID (from POST /projects/{id}/imports).

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/imports/6d1f0c2a-8b3e-4f5a-9c7d-2e1f0a9b8c7d" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "import": {
    "id": "6d1f0c2a-8b3e-4f5a-9c7d-2e1f0a9b8c7d",
    "kind": "mspdi",
    "status": "preview",
    "file_name": "launch-plan.xml",
    "preview": {
      "name": "Launch plan",
      "counts": {
        "tasks": 312,
        "summaries": 41,
        "milestones": 9,
        "links": 356,
        "assignments": 288,
        "calendars": 2
      },
      "baselines": [
        0
      ],
      "customFields": [
        {
          "key": "workstream",
          "label": "Workstream",
          "type": "text"
        }
      ],
      "resources": [
        {
          "ref": "3",
          "name": "Ada Rossi",
          "email": "ada@acme.dev",
          "suggested": "f3a2b1c0-9d8e-4f7a-8b6c-5d4e3f2a1b0c"
        },
        {
          "ref": "7",
          "name": "Contractor",
          "email": null,
          "suggested": null
        }
      ],
      "settings": {
        "projectStart": "2026-10-05T08:00",
        "statusDate": null,
        "minutesPerDay": 480,
        "minutesPerWeek": 2400,
        "daysPerMonth": 20,
        "calendar": "Standard"
      },
      "sample": [
        {
          "ref": "1",
          "level": 1,
          "name": "Discovery",
          "durationMinutes": 4800,
          "start": "2026-10-05T08:00",
          "finish": "2026-10-16T17:00"
        }
      ],
      "existingItems": 0,
      "csv": null
    },
    "warnings": [
      {
        "code": "split_task",
        "message": "2 split tasks were imported as one continuous bar.",
        "refs": [
          "58",
          "61"
        ]
      }
    ],
    "stats": {},
    "error": null,
    "created_at": "2026-09-28T09:20:11Z",
    "applied_at": null
  }
}
StatusWhen
200Success
401Missing or invalid API key.
404Project or import not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Parse, apply or discard an import

POST/projects/{id}/imports/{importId}

`parse` reads the uploaded file and builds the preview (for a CSV file you can pass the column `mapping` and the `dateOrder`, otherwise both are guessed). `apply` creates the items, links, assignments, calendars, baselines and custom fields in one batch: `append` adds them after the existing items, `replace` deletes the existing items first. `resourceMap` maps each resource of the file to a project member (`resourceId` from the preview suggestions) or to nobody. `discard` deletes the uploaded file. Project managers only.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
importIdrequiredstringImport UUID (from POST /projects/{id}/imports).

Body parameters

NameTypeDescription
actionrequiredstringWhat to do with the import.One of: parse, apply, discard
mappingoptionalobjectCSV only, with `parse`: field name to zero-based column index, for example `{"name": 0, "duration": 2}`. Fields: `id`, `name`, `outline_level`, `wbs`, `duration`, `start`, `finish`, `predecessors`, `percent_complete`, `status`, `notes`, `resources`, `milestone`, `deadline`, `priority`.
dateOrderoptionalstringCSV only, with `parse`: how dates are written.One of: ymd, dmy, mdy
modeoptionalstringWith `apply`: add to the plan or replace it.One of: append, replaceDefault: append
applySettingsoptionalbooleanWith `apply`: also take the project start, status date, day length and calendars from the file.Default: true
resourceMapoptionalobjectWith `apply`: resource `ref` of the preview to a project member `resourceId`, or null for nobody. Unmapped resources are not assigned.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/imports/6d1f0c2a-8b3e-4f5a-9c7d-2e1f0a9b8c7d" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "action": "apply", "mode": "append", "resourceMap": { "3": "f3a2b1c0-9d8e-4f7a-8b6c-5d4e3f2a1b0c", "7": null } }'

Request body

JSON
{
  "action": "apply",
  "mode": "append",
  "resourceMap": {
    "3": "f3a2b1c0-9d8e-4f7a-8b6c-5d4e3f2a1b0c",
    "7": null
  }
}

Response

JSON
{
  "status": "applying"
}
StatusWhen
200`discard` done.
202`parse` or `apply` started. Poll GET /projects/{id}/imports/{importId}.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
403The key owner is not a manager of this project.
404Project or import not found or not accessible by this key.
409The import is not in a state that allows this action (apply needs a preview; a running import cannot be discarded).
429Rate limit exceeded (60/min/key).

Export a plan

GET/projects/{id}/export

Downloads the project plan as an MS Project XML file (tasks, outline, dependencies, constraints, deadlines, progress, calendars, resources, assignments and saved baselines) that Project desktop opens with File > Open, or as a CSV file with one row per item. Dates are wall-clock times in the plan time zone.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Query parameters

NameTypeDescription
formatrequiredstring`mspdi` for MS Project XML, `csv` for a spreadsheet.One of: mspdi, csv

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/export?format=mspdi" \
  -H "Authorization: Bearer fr_your_api_key" \
  -o plan.xml

Response

XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Project xmlns="http://schemas.microsoft.com/project">
  <SaveVersion>14</SaveVersion>
  <Name>Billing.xml</Name>
  <Title>Billing</Title>
  <StartDate>2026-09-28T08:00:00</StartDate>
  <Tasks>
    <Task>
      <UID>12</UID>
      <Name>Move invoices to Paddle</Name>
      <Start>2026-09-28T08:00:00</Start>
      <Finish>2026-10-02T17:00:00</Finish>
      <Duration>PT40H0M0S</Duration>
      <PercentComplete>40</PercentComplete>
    </Task>
  </Tasks>
</Project>
StatusWhen
200The file, with a `Content-Disposition: attachment` header.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Exporting plans is not part of the plan (Starter and above).
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

List your logged time

GET/time-entries

Returns the hours the key owner logged between two dates, oldest first, with the status of the weekly timesheet each entry belongs to. Only the key owner's own time: there is no way to read someone else's entries through this endpoint.

Query parameters

NameTypeDescription
fromrequiredstringFirst day, YYYY-MM-DD.
torequiredstringLast day, YYYY-MM-DD, at most 92 days after `from`.

Request

curl "https://www.flowrelay.it/api/v1/time-entries?from=2026-09-28&to=2026-10-04" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "entries": [
    {
      "id": "5e4d3c2b-1a09-4f8e-9d7c-6b5a4f3e2d1c",
      "projectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "item": "FR-12",
      "date": "2026-09-29",
      "minutes": 90,
      "note": "Pairing on the retry logic",
      "source": "manual",
      "status": "draft"
    }
  ]
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
429Rate limit exceeded (60/min/key).

Log time

POST/time-entries

Adds time to the key owner's own timesheet for the week of `date`. Logging again on the same item and day adds up and never overwrites. Organization projects accept time only while the organization has time tracking turned on, and a submitted or approved week can no longer change. Costs no credits.

Body parameters

NameTypeDescription
projectIdrequiredstringProject UUID (from GET /projects).
refoptionalstringItem key such as `FR-12`, or the item id. Without it the time counts on the project as a whole.
daterequiredstringDay worked, YYYY-MM-DD.
minutesrequiredintegerWhole minutes, 1 to 1440. A day never holds more than 24 hours.
noteoptionalstringUp to 500 characters.

Request

curl "https://www.flowrelay.it/api/v1/time-entries" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "projectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ref": "FR-12", "date": "2026-09-29", "minutes": 90 }'

Request body

JSON
{
  "projectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "ref": "FR-12",
  "date": "2026-09-29",
  "minutes": 90
}

Response

JSON
{
  "logged": 90,
  "date": "2026-09-29",
  "week": "2026-09-28"
}
StatusWhen
201Time logged.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
403The organization has not turned time tracking on.
404Project or item not found or not accessible by this key.
409The week is submitted or approved.
429Rate limit exceeded (60/min/key).

Get earned value and costs

GET/projects/{id}/evm

Returns the cost picture of a plan at its status date: planned and actual cost, and the earned value figures (planned value, earned value, variances, SPI, CPI, TCPI and the three estimates at completion) measured against a baseline. Amounts are whole cents in the currency of the organization. Actual cost comes from logged hours at the rate in force that day when any were logged, otherwise from progress. Project managers only, on plans that include costs. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Query parameters

NameTypeDescription
baselineoptionalintegerBaseline slot to measure against, 0 to 10.Default: 0

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/evm" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "currency": "EUR",
  "statusDate": "2026-09-29",
  "baseline": 0,
  "actualsFrom": "timesheets",
  "plannedCostCents": 4820000,
  "actualCostCents": 2130000,
  "budgetCents": 5000000,
  "earnedValue": {
    "budgetAtCompletionCents": 4800000,
    "plannedValueCents": 2400000,
    "earnedValueCents": 2160000,
    "actualCostCents": 2130000,
    "scheduleVarianceCents": -240000,
    "costVarianceCents": 30000,
    "spi": 0.9,
    "cpi": 1.01,
    "tcpi": 0.99,
    "estimateAtCompletionCents": {
      "cpi": 4733000,
      "budgetRate": 4770000,
      "cpiSpi": 4818000
    },
    "estimateToCompleteCents": 2603000,
    "varianceAtCompletionCents": 67000
  },
  "curve": [
    {
      "weekEnding": "2026-10-04",
      "baselineCents": 2500000,
      "currentCents": 2300000
    }
  ],
  "generatedFor": "2026-09-29"
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Costs and earned value are not part of the plan (Business and above).
403The key owner is not a manager of this project.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Forecast the finish of a plan

GET/projects/{id}/forecast

Simulates the plan thousands of times and returns, for the project and for each open milestone, the dates by which half, four out of five and nineteen out of twenty of the runs are done, the chance of meeting the target finish or a milestone deadline and the items most often on the critical path. mode=schedule (default) varies the durations of the open tasks (uncertainty low, medium or high; tasks marked as estimates vary one step wider); mode=throughput uses how many items the team finished each week over the last twelve weeks and needs at least four weeks of history. The same plan version always gives the same forecast. Dates are wall-clock times in the plan time zone. Included from the Business plan. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Query parameters

NameTypeDescription
modeoptionalstringWhat to simulate.One of: schedule, throughputDefault: schedule
uncertaintyoptionalstringHow far durations may vary in schedule mode.One of: low, medium, highDefault: medium

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/forecast" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "mode": "schedule",
  "uncertainty": "medium",
  "iterations": 2000,
  "planVersion": 41,
  "project": {
    "plan": "2026-12-18T17:00",
    "target": "2026-12-11T17:00",
    "p50": "2026-12-22T17:00",
    "p80": "2027-01-08T17:00",
    "p95": "2027-01-20T17:00",
    "chance": 0.18
  },
  "milestones": [
    {
      "id": "5f2d6a10-0e3b-4c7a-9d18-2b6c4e8f1a30",
      "ref": "WEB-14",
      "title": "Design freeze",
      "plan": "2026-10-09T17:00",
      "deadline": null,
      "p50": "2026-10-12T17:00",
      "p80": "2026-10-16T17:00",
      "p95": "2026-10-23T17:00",
      "chance": 0.31
    }
  ],
  "critical": [
    {
      "id": "8a1c3e5f-7b9d-4f20-8c41-6d5e4f3a2b10",
      "ref": "WEB-7",
      "title": "Payment webhook",
      "index": 0.92
    }
  ],
  "histogram": [
    {
      "from": "2026-12-15",
      "to": "2026-12-19",
      "count": 240
    }
  ]
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Forecasts are not part of the plan (Business and above).
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Ask a what-if question about a plan

POST/projects/{id}/whatif

Turns a what-if question written in words into changes to the work (set a duration, delay a start, cancel an item, add a link) and lets the scheduler compute the result: the new finish of the project and of each milestone, how many items move and what becomes critical. The model only maps the words to changes using the keys of the plan; every date comes from the scheduler. Whatever cannot be expressed is listed in left_out. Nothing is saved and the plan is not changed. Viewers cannot ask. Included from the Business plan. Costs 5 credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Body parameters

NameTypeDescription
questionrequiredstringThe what-if question, 5 to 500 characters.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/whatif" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "question": "What if the payment integration takes three weeks longer?" }'

Request body

JSON
{
  "question": "What if the payment integration takes three weeks longer?"
}

Response

JSON
{
  "explanation": "Made WEB-7 three weeks long, assuming the current dependencies.",
  "changes": [
    "Set WEB-7 to 3w"
  ],
  "left_out": [],
  "comparison": {
    "projectFinish": {
      "now": "2026-12-18T17:00",
      "scenario": "2027-01-08T17:00",
      "deltaWorkingDays": 15
    },
    "milestones": [
      {
        "ref": "WEB-14",
        "title": "Design freeze",
        "now": "2026-10-09T17:00",
        "scenario": "2026-10-30T17:00",
        "deltaWorkingDays": 15
      }
    ],
    "moved": 4,
    "criticalBecame": 1,
    "criticalLeft": 0,
    "warnings": 0
  },
  "errors": []
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Scenarios are not part of the plan (Business and above), or the plan is out of credits.
403The key owner is a viewer of this project.
404Project not found or not accessible by this key.
504The answer took longer than 60 seconds.
429Rate limit exceeded (60/min/key).

Get the portfolio of an organization

GET/portfolio

Returns the projects of an organization that the key owner can open, each with its progress, forecast finish, next milestone, open risks and health. Health is a verdict (green, amber or red) computed every night from the plan: schedule slip against the baseline or the target finish, overdue items, scope added since the baseline and the latest build, deploy and incident signals. A project manager can set the verdict by hand, and then overridden is true with the comment. Costs are not included here: use GET /projects/{id}/evm. Included from the Business plan. Costs no credits.

Query parameters

NameTypeDescription
organization_idrequiredstringOrganization UUID (from GET /projects, the organizationId of a project).

Request

curl "https://www.flowrelay.it/api/v1/portfolio?organization_id=ORGANIZATION_ID" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "organizationId": "4b1f0c6e-2a3d-4e5f-8a9b-0c1d2e3f4a5b",
  "projects": [
    {
      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "key": "WEB",
      "name": "Website relaunch",
      "status": "active",
      "programId": null,
      "percentComplete": 62,
      "projectStart": "2026-08-03T08:00",
      "scheduledFinish": "2026-12-18T17:00",
      "targetFinish": "2026-12-11T17:00",
      "openRisks": 3,
      "nextMilestone": {
        "ref": "WEB-14",
        "title": "Design freeze",
        "finish": "2026-10-09T17:00"
      },
      "health": {
        "verdict": "amber",
        "overridden": false,
        "comment": null,
        "schedule": "amber",
        "cost": null,
        "scope": "green",
        "delivery": "green",
        "computedOn": "2026-09-29",
        "slipWorkingDays": 5,
        "overdueItems": 2,
        "openItems": 31
      }
    }
  ],
  "programs": [
    {
      "id": "2f6b1d0e-9a8b-4c7d-8e6f-5a4b3c2d1e0f",
      "name": "Growth"
    }
  ],
  "dependencies": [
    {
      "from": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "to": "0d3b5a7c-1e2f-4a6b-9c8d-7e6f5a4b3c2d",
      "count": 2
    }
  ]
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402The organization plan does not include portfolio management (Business and above).
404Organization not found or the key owner is not a member.
429Rate limit exceeded (60/min/key).

List the RAID register

GET/projects/{id}/raid

Returns the risks, assumptions, issues, decisions and dependencies of a project, highest number first. Entries that are not closed by default. The score is probability times impact, present on risks and issues.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Query parameters

NameTypeDescription
kindoptionalstringFilter by type.One of: risk, assumption, issue, decision, dependency
statusoptionalstringFilter by status. Omit for every entry that is not closed.One of: open, monitoring, closed, all
limitoptionalintegerMax records to return (1-200, default 50).Default: 50

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/raid" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "entries": [
    {
      "id": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
      "number": 4,
      "type": "risk",
      "title": "Payment provider certification may slip",
      "description": "",
      "status": "open",
      "probability": 3,
      "impact": 5,
      "score": 15,
      "response": "Book the certification slot now.",
      "ownerId": null,
      "dueOn": "2026-10-16",
      "item": "FR-12",
      "createdAt": "2026-09-28T09:10:00Z"
    }
  ]
}
StatusWhen
200Success
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

List the automation rules of a project

GET/projects/{id}/automations

Returns the automation rules of a project: each with a plain sentence that says what starts it, what it checks and what it does, its trigger, conditions and actions as stored, how many times it ran and how the last run went. Read only: rules are changed in the app. Available from the Team plan. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/automations" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "automations": [
    {
      "id": "5c4b3a29-1807-4f6e-9d5c-4b3a2918f7e6",
      "name": "Close out",
      "enabled": true,
      "summary": "When an item moves to Done, and priority is at least High: notify the assignees.",
      "trigger": {
        "type": "status_changed",
        "to": "done"
      },
      "conditions": [
        {
          "field": "priority",
          "op": "gte",
          "value": 3
        }
      ],
      "actions": [
        {
          "type": "notify",
          "to": "assignees",
          "message": "{{key}} is done"
        }
      ],
      "runCount": 12,
      "lastRunAt": "2026-10-08T14:20:00Z",
      "lastStatus": "ok"
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

List the plan templates of a project

GET/projects/{id}/templates

Returns the templates saved for the project: those of its organization, or your own on a personal project. A template is a whole plan or one item with its subtasks, kept as names, notes, durations and links, never people or dates. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/templates" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "templates": [
    {
      "id": "7e6d5c4b-3a29-4180-b6f5-e4d3c2b1a098",
      "kind": "item",
      "name": "Release checklist",
      "description": "Steps before a release",
      "itemCount": 6,
      "createdAt": "2026-09-20T09:00:00Z"
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Add a template to a plan

POST/projects/{id}/templates/{templateId}/apply

Adds the items of a template to the plan, at the top level or under an existing item, as one change that the history can undo. Only project managers can. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
templateIdrequiredstringTemplate UUID (from GET /projects/{id}/templates).

Body parameters

NameTypeDescription
parentoptionalstringKey or id of the item to add the template under. Omit for the top level.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/templates/7e6d5c4b-3a29-4180-b6f5-e4d3c2b1a098/apply" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "parent": "FR-12" }'

Request body

JSON
{
  "parent": "FR-12"
}

Response

JSON
{
  "created": 6,
  "version": 42
}
StatusWhen
201Items created and scheduled.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Work management is not part of the plan, or the project reached its item limit.
403The key owner is not a manager of the project.
404Project, template or parent item not found or not accessible by this key.
409The plan kept changing while the items were saved. Retry.
429Rate limit exceeded (60/min/key).

List the change requests of a project

GET/projects/{id}/approvals

Returns the last 50 change requests of an organization project: what was asked in plain language, who asked, who decided and when. Change requests are included from the Business plan; on a personal project or a plan without them the list is empty. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Query parameters

NameTypeDescription
statusoptionalstringUse pending to list only the requests waiting for a decision.One of: pending

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/approvals" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "approvals": [
    {
      "id": "2c1b0a9f-8e7d-4c6b-9a5f-4e3d2c1b0a9f",
      "kind": "scope",
      "title": "Move the launch by one week",
      "note": "The vendor needs another week.",
      "summary": [
        "Change duration of FR-12 \"Launch\""
      ],
      "status": "pending",
      "requestedBy": "Ada Lovelace",
      "decidedBy": null,
      "decidedAt": null,
      "decisionNote": null,
      "createdAt": "2026-09-28T09:00:00Z"
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

Ask for a change to a work item

POST/projects/{id}/approvals

Creates a change request for one work item. A second person decides it in the plan, and approving applies the change as the approver. Use it when the key owner may not make the change directly, or wants it reviewed. Changes use the same fields as PATCH on a work item. Organization projects on the Business plan or above only. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Body parameters

NameTypeDescription
itemrequiredstringKey such as FR-12 or id of the work item.
titlerequiredstringWhat you want changed, 1 to 200 characters.
noteoptionalstringWhy, up to 2,000 characters.
changesrequiredobjectThe fields to change: title, description, status, priority, blocked, percentComplete, duration or deadline.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/approvals" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "item": "FR-12", "title": "Move the launch by one week", "note": "The vendor needs another week.", "changes": { "duration": "6d" } }'

Request body

JSON
{
  "item": "FR-12",
  "title": "Move the launch by one week",
  "note": "The vendor needs another week.",
  "changes": {
    "duration": "6d"
  }
}

Response

JSON
{
  "id": "2c1b0a9f-8e7d-4c6b-9a5f-4e3d2c1b0a9f",
  "status": "pending"
}
StatusWhen
201Request created and the approvers notified.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Change approvals are not part of the plan.
403The key owner cannot change this plan, or the change touches a field the key owner may not see.
404Project or item not found or not accessible by this key.
409The key owner has too many requests waiting for a decision.
429Rate limit exceeded (60/min/key).

Decide a change request

PATCH/projects/{id}/approvals/{approvalId}

Approves or rejects a pending change request, or withdraws one you made. Approving applies the change as the approver and reschedules the plan. A request needs a second person: the key owner cannot approve or reject a request they made. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).
approvalIdrequiredstringChange request UUID (from GET /projects/{id}/approvals).

Body parameters

NameTypeDescription
decisionrequiredstringWhat to do with the request. Only the person who asked can withdraw.One of: approve, reject, withdraw
noteoptionalstringWhy, up to 1,000 characters.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/approvals/approvalId" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X PATCH \
  -H "Content-Type: application/json" \
  -d '{ "decision": "approve", "note": "Fine by me." }'

Request body

JSON
{
  "decision": "approve",
  "note": "Fine by me."
}

Response

JSON
{
  "status": "approved",
  "batchId": "5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a"
}
StatusWhen
200Request decided. `status` is approved, rejected or withdrawn.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
402Change approvals are not part of the plan.
403The key owner cannot decide change requests, asked for this one, or tried to withdraw a request made by someone else.
404Project or request not found or not accessible by this key.
409The request is no longer pending, was decided in the meantime, or applying it failed (`status` is failed).
429Rate limit exceeded (60/min/key).

Add a RAID entry

POST/projects/{id}/raid

Adds a risk, assumption, issue, decision or dependency to the register of a project. Viewers cannot add. Probability and impact are 1 to 5. Costs no credits.

Path parameters

NameTypeDescription
idrequiredstringProject UUID (from GET /projects).

Body parameters

NameTypeDescription
kindrequiredstringType of the entry.One of: risk, assumption, issue, decision, dependency
titlerequiredstring1 to 300 characters.
descriptionoptionalstringUp to 10,000 characters.
probabilityoptionalinteger1 to 5, for risks and issues.
impactoptionalinteger1 to 5, for risks and issues.
responseoptionalstringThe planned response, or for a decision what was decided and why.
statusoptionalstringDefaults to open.One of: open, monitoring, closed
dueOnoptionalstringYYYY-MM-DD.

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/raid" \
  -H "Authorization: Bearer fr_your_api_key" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "kind": "risk", "title": "Payment provider certification may slip", "probability": 3, "impact": 5, "dueOn": "2026-10-16" }'

Request body

JSON
{
  "kind": "risk",
  "title": "Payment provider certification may slip",
  "probability": 3,
  "impact": 5,
  "dueOn": "2026-10-16"
}

Response

JSON
{
  "id": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
  "number": 4
}
StatusWhen
201Entry added.
400The body or a query parameter is invalid: an unknown field, an unknown source, an unsupported filter dimension or an out-of-range number. The response names the offending field and lists the allowed values.
401Missing or invalid API key.
403The key owner is a viewer of this project.
404Project not found or not accessible by this key.
429Rate limit exceeded (60/min/key).

List project digests

GET/projects/{id}/digests

Lists past scheduled activity digests for a project, newest first.

Path parameters

NameTypeDescription
idrequiredstringProject UUID.

Query parameters

NameTypeDescription
limitoptionalintegerMax records to return (1-50, default 10).Default: 10

Request

curl "https://www.flowrelay.it/api/v1/projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/digests" \
  -H "Authorization: Bearer fr_your_api_key"

Response

JSON
{
  "digests": [
    {
      "id": "7c9e3b12-4567-89ab-cdef-0123456789ab",
      "projectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "generatedBy": "11111111-2222-3333-4444-555555555555",
      "periodStart": "2026-07-17T00:00:00Z",
      "periodEnd": "2026-07-24T00:00:00Z",
      "content": {
        "title": "Weekly Digest",
        "summary": "Major progress on API v1 and checkout flow."
      },
      "markdown": "# Weekly Digest\n...",
      "createdAt": "2026-07-24T00:00:05Z"
    }
  ]
}
StatusWhen
200Success
401Missing or invalid API key.
429Rate limit exceeded (60/min/key).
404Project not found or not accessible by this key.