> For the complete documentation index, see [llms.txt](https://portavi.gitbook.io/portavi-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://portavi.gitbook.io/portavi-docs/developers/rest-api.md).

# The Portavi API

The Portavi API lets your own code read your workspace: to load projects and their health into a data warehouse, build a report Portavi doesn't have, or keep another system in step. It is **read-only**. Nothing you send through it can add, edit or delete anything in Portavi.

The API is included on **Scale** and above.

## What it can read

| Resource                           | Address                           | Filters                                                             |
| ---------------------------------- | --------------------------------- | ------------------------------------------------------------------- |
| Portfolios                         | `/portfolios`, `/portfolios/{id}` |                                                                     |
| Programmes                         | `/programmes`, `/programmes/{id}` | `portfolio_id`                                                      |
| Projects                           | `/projects`, `/projects/{id}`     | `programme_id`, `portfolio_id`, `health_status`, `lifecycle_status` |
| Health history                     | `/health-history`                 | `project_id`, `field`                                               |
| Tasks                              | `/tasks`, `/tasks/{id}`           | `project_id`, `status_category`                                     |
| Milestones                         | `/milestones`                     | `project_id`                                                        |
| Phases                             | `/phases`                         | `project_id`                                                        |
| Sprints                            | `/sprints`                        | `project_id`                                                        |
| Flagged items                      | `/flagged-items`                  | `project_id`                                                        |
| Risks                              | `/risks`                          | `project_id`, `programme_id`                                        |
| Issues                             | `/issues`                         | `project_id`, `programme_id`, `status`                              |
| Assumptions                        | `/assumptions`                    | `project_id`, `programme_id`                                        |
| Dependencies                       | `/dependencies`                   |                                                                     |
| Decisions                          | `/decisions`                      | `project_id`, `programme_id`, `portfolio_id`, `status`              |
| Lessons learned                    | `/lessons`                        | `project_id`, `programme_id`                                        |
| Change requests                    | `/change-requests`                | `project_id`, `programme_id`, `status`                              |
| Benefits                           | `/benefits`                       | `programme_id`                                                      |
| Benefit measurements               | `/benefit-measurements`           | `programme_id`                                                      |
| Objectives, with their key results | `/objectives`                     | `portfolio_id`                                                      |
| Budget entries (actual spend)      | `/budget-entries`                 | `project_id`, `programme_id`, `portfolio_id`                        |
| Members                            | `/members`                        | `role`                                                              |

Every address starts with `https://app.portavipmo.com/api/v1`. The [API reference](https://app.portavipmo.com/api/v1/openapi.json) lists every field, as an OpenAPI 3.1 document you can load into Postman or a client generator.

## What a token can see

The API reads **as the person who created the token**, and sees exactly what they see in Portavi. A PMO manager's token reads the whole workspace; a project manager's reads the projects they own. If their role changes, or they leave the workspace, what the token can read changes straight away.

Each token reads one workspace. Portfolios, programmes, budgets and change requests are only there if the workspace has them switched on. Where a feature is off, its addresses answer `feature_disabled`, and items on a switched-off level are left out of other lists: with programmes off, for example, `/risks` has no programme risks.

Two lists are the same for everyone. `/members` lists every member, with their name and role only, as anyone in the workspace can see them. Decisions recorded for the whole workspace rather than a project, programme or portfolio go only to PMO managers and executives, as only they see the Governance page.

`/dependencies` lists, for roles other than PMO manager and executive, the dependencies recorded on a programme or portfolio they can see, or with a project or programme at either end that they can see. Portavi can show a few more on a project's page, where one end is a phase, sprint or milestone of that project.

## Your first call

1. Create an access token under **Settings → Security → API access**. [Connecting an AI client](/portavi-docs/ai/connecting-ai-clients.md#creating-an-access-token) has the steps. The same tokens work for the API and for AI tools.
2. Send it in the `Authorization` header as a bearer token:

```bash
curl https://app.portavipmo.com/api/v1/projects?limit=2 \
  -H "Authorization: Bearer <token>"
```

The answer is a page of projects:

```json
{
  "data": [
    {
      "id": "3f6b1c2e-8a41-4d7e-9c0a-5b2d7e1f9a63",
      "name": "Mobile App Redesign",
      "type": "scrum",
      "lifecycle_status": "active",
      "health_status": "at_risk",
      "programme_id": "0c9e2a4b-6d13-4f8a-b7e5-2a1c9d3f4e80",
      "owner_id": "a71d5e93-2c4f-4b08-8e6a-9f3b1c7d2e54",
      "source_tool": "jira",
      "target_completion_date": "2026-12-18",
      "updated_at": "2026-11-12T09:41:07.512Z"
    }
  ],
  "next_cursor": "WyIyMDI2LTExLTEy..."
}
```

Some fields are left out here; the reference has them all.

## Conventions

* **Field names** are `snake_case`. **Times** are ISO 8601 in UTC; **dates** are `YYYY-MM-DD`.
* **Statuses are codes**, the same in every language: `on_track`, `at_risk`, `delayed`. A project whose health hasn't been worked out yet has `null`.
* **Programme health** is rolled up from the programme's projects, the same way Portavi shows it: the worst project health wins, and a completed project counts as on track. A delayed project makes the programme `at_risk` until the programme's own end date has passed; only then is it `delayed`.
* **Budgets.** Projects, programmes and portfolios carry a `budget`: the currency, the total (or `per_month` for open-ended work), the baseline and the reserves. It's `null` when the workspace has budgeting switched off. What's been spent is in `/budget-entries`, one row per cost.
* **Ids** are UUIDs. An `owner_id` or `assignee_id` is a Portavi member's id.
* **New fields can appear.** Adding a field or a resource doesn't count as a breaking change, so ignore fields you don't know rather than failing on them. A breaking change would come as a new version, `/api/v2`.

## Next

* [Paging and incremental loads](/portavi-docs/developers/paging-and-incremental-loads.md): reading every row, then only what changed.
* [Errors and rate limits](/portavi-docs/developers/errors-and-rate-limits.md): what each error means and what to do about it.
* [Power BI and Excel](/portavi-docs/developers/power-bi.md): the same data as an OData feed, with no code.

## Keeping tokens safe

A token reads what its owner can read, so keep it out of source control and shared files: put it in your secrets store or an environment variable. Use one token per integration, named after it, so you can revoke one without breaking the others. [Managing your tokens](/portavi-docs/ai/connecting-ai-clients.md#managing-your-tokens) covers expiry and revoking.
