# Functions API

> Read and manage the workspace's functions (per-area access), assign them to members and invitations, and read the caller's own access.

Source: https://productos.ca/documentation/api/v1/functions (last reviewed 2026-09-30)

A function grants `none`, `view`, `comment` or `edit` on each **area** of a workspace. What a caller can do in an area is the lower of their role and their function; the owner is never limited, and a member with no function is unrestricted. How it works in the app: [Functions & Access](https://productos.ca/documentation/pages/settings/functions-and-access).

Areas: `feedback`, `themes`, `work`, `initiatives`, `releases`, `outcomes`, `products`, `customers`, `team`, `strategy`, `market-intelligence`, `go-to-market`, `sales-intelligence`, `knowledge`, `code`, `design-system`.

## Your own access

`GET /api/v1/access` returns the caller's role, function and level in every area. For an API token it is the token holder's function, capped by the token's role.

```json title="200 response"
{
  "data": {
    "role": "member",
    "function": { "id": "7d7f…", "name": "Sales and marketing" },
    "limited_by_function": true,
    "areas": { "feedback": "edit", "work": "view", "themes": "none", "…": "…" }
  }
}
```

A request to an area the caller cannot reach is refused with `403` and a message that names the function and the area, for example "Your function, Sales and marketing, gives you view access to Work; this needs edit access."

## Functions

| Method | Path | Who | What |
| :--- | :--- | :--- | :--- |
| `GET` | `/api/v1/functions` | Any member | Every function, with `member_count`. `meta.enabled` says whether the workspace can create and assign functions; `meta.can_manage` whether the caller can. |
| `POST` | `/api/v1/functions` | Owner, admin | Create one. Body: `name` (required, 60 characters at most), `description`, `access`, `landing_path`, `nav`, `dashboard`, `sort_order`. `409` when the name is taken. |
| `PATCH` | `/api/v1/functions/{id}` | Owner, admin | Change any of those fields. `access` replaces the whole map; an area left out is `none`. |
| `DELETE` | `/api/v1/functions/{id}` | Owner, admin | Delete it. Its members are left with no function, unless `?reassign_to={function id}` moves them first. |
| `POST` | `/api/v1/functions/starters` | Owner, admin | Add the starter functions (Product, Engineering, Leadership, Sales and marketing, Support) the workspace does not have yet. |

`access` maps an area to a level: `{ "feedback": "edit", "work": "view" }`. An unknown area or level is refused with `422`, never dropped.

`landing_path` is an in-app page such as `/features?mywork=true`, where the function's people arrive after signing in. `nav` is the sidebar they start from: `{ "pinned": ["/roadmap", "/releases"], "hidden": [], "expanded": ["gtm"] }`, with at most 8 pinned pages, paths from the sidebar, and section ids (`golden-thread`, `workspace`, `strategy`, `intelligence`, `gtm`, `sales`, `tools`). Anything else is refused with `422`.

`dashboard` is the dashboard the function's people start with, as two columns, `{ "main": ["my-work", "blocked-overdue"], "side": ["upcoming-releases", "activity-log"] }`, where the first main widget leads the page, or as a list, `{ "widgets": ["my-work", "upcoming-releases"] }`, which is split into columns by each widget's usual place. The widget ids are `attention`, `golden-thread`, `my-work`, `my-prs-sessions`, `feedback-triage`, `top-feedback`, `close-the-loop`, `account-health`, `revenue-at-risk`, `active-features`, `blocked-overdue`, `sprint-progress`, `dates-moved`, `upcoming-releases`, `recently-shipped`, `outcomes-okrs`, `initiatives-at-risk`, `investment-mix`, `upcoming-launches`, `deal-blockers`, `win-loss`, `market-signals`, `team-capacity`, `product-backlog` and `activity-log`. An unknown widget, a widget in both columns, or a widget the function's own `access` cannot view is refused with `422`.

An admin cannot change or delete the function they hold (`403`). Creating, changing and assigning need functions to be available for the workspace; clearing an assignment and deleting a function always work, since both only lift a limit.

## Assigning

- `PATCH /api/v1/members/{id}` with `{ "function_id": "…" }` gives a member a function; `null` clears it. An admin cannot change their own.
- `POST /api/v1/invitations` and `POST /api/v1/invitations/{id}/resend` take `function_id`; it applies when the invitation is accepted.
