PM Configuration
These endpoints let you read and change your project management (PM) configuration without the LinearB app: which PM integrations you have, which boards and projects are collected, and which PM entities each team is scoped to.
Providers: Jira and Azure Boards.
Authentication: an API key, sent as the x-api-key header (see Overview). Only an admin can create an API key, and every key acts as an admin of your organization on these endpoints - it can read, and change what is collected and each team's scope.
Every endpoint that acts on an integration takes its id explicitly, because an organization can have several PM integrations. Start with List Integrations to get those ids.
| Endpoint | What it does |
|---|---|
GET /api/v1/integrations?type=pm | List your integrations (type=pm for PM only) |
GET /api/v2/pm/entities/{entity_type} | Read PM entities of one type: what exists, what is collected, and what uses it |
PATCH /api/v2/pm/integrations/{integration_id}/entities/{entity_type} | Select or deselect boards / projects for collection |
GET /api/v1/pm/config/teams/{team_id}/scope | Read a team's PM scope |
PATCH / POST /api/v1/pm/config/teams/scope | Write the PM scope of one or more teams |
DELETE /api/v1/pm/config/teams/{team_id}/scope/{scope_key} | Clear one key of a team's PM scope |
DELETE /api/v1/pm/config/teams/{team_id}/scope | Clear a team's whole PM scope on one integration |
List Integrations
Lists your organization's integrations: PM (Jira and Azure Boards) and git. Use type=pm to list only the PM integrations these endpoints take.
HTTP request
GET https://public-api.linearb.io/api/v1/integrations?type=pm
Query parameters
| Parameter name | Value | Description |
|---|---|---|
| type | string | pm or git. Omitted lists both. |
| provider | string | Only these providers, comma-separated, e.g. jira,azure_boards. |
| include_invalid | boolean | Also list deleted integrations, each with deleted_at. (Default: false) |
Responses
200 - Successful Response
{
"items": [
{"id": 1001, "type": "pm", "provider": "jira", "name": "Jira", "state": "ok", "auth_type": "oauth2"},
{"id": 1002, "type": "pm", "provider": "azure_boards", "name": "Azure Boards", "state": "failing", "auth_type": "token",
"failing_reason": "PM integration failure. Review this integration in Settings > Project Management."}
]
}
idis the integration id that every other endpoint takes.typesays whether it is apmor agitintegration.stateisok,failing,insufficient-permission,in-progress,inactive,cleanup-requested,cleanup-in-progressorcleanup-failed. Every integration that is not deleted is listed and can be read.- An
ok,failingorinsufficient-permissionPM integration can be changed. One that is still being connected (in-progress),inactive, or being removed (cleanup-*) is read-only: a write that names it returns400saying why.
400 - Bad Request (for example, type other than pm / git, or an unknown provider)
403 - Forbidden
List PM Entities
Reads the PM entities of one type, across your integrations.
HTTP request
GET https://public-api.linearb.io/api/v2/pm/entities/{entity_type}
Path parameters
| Parameter name | Value | Description |
|---|---|---|
| entity_type | string | Jira: boards, projects, epics, labels, fields. Azure Boards: projects, teams, areas. |
Query parameters
| Parameter name | Value | Description |
|---|---|---|
| integration_ids | string | Comma-separated integration ids, up to 50. Omitted = all your PM integrations that are not deleted. |
| is_selected_for_collection | boolean | Filter by collection status. Only valid on Jira boards / projects and Azure projects. |
| include_invalid | boolean | Also return entities the provider no longer exposes. (Default: false) |
| with_used_by | boolean | Return used_by on boards and projects. Set false for a faster read. (Default: true) |
| limit | integer | Page size. (Minimum: 1, Maximum: 1000, Default: 100) |
| offset | integer | Entities to skip, counted across all integrations. The next page is offset + limit, until total. (Default: 0) |
Responses
200 - Successful Response
{
"total": 1,
"offset": 0,
"type": "boards",
"integrations": [
{
"integration_id": 1001,
"provider": "jira",
"integration_name": "Jira",
"entities": [
{
"entity_provider_id": "109",
"name": "Payments Scrum Board",
"state": "accessible",
"is_selected_for_collection": true,
"selected_last_updated_at": "2026-08-06T10:04:31.327Z",
"used_by": {"teams": [{"id": 4412, "name": "Payments"}], "projects": []}
}
]
}
]
}
entity_provider_idis the provider's id. The write endpoints take it.is_selected_for_collectionandselected_last_updated_atappear only on Jira boards / projects and Azure projects.used_by(boards and projects only) lists what depends on the entity. A deselect is refused while it is not empty.- Azure
teamscarry theirparent_project, and Azureareascarry theirteams. That is what a team scope'sproject_team_areasneeds.
400 - Bad Request (for example, a type the provider does not have)
403 - Forbidden
404 - Not Found (an integration id that is not a live PM integration of your organization)
Select PM Entities for Collection
Selects or deselects boards / projects of one integration for collection. Same as Settings > Project Management in the app.
HTTP request
PATCH https://public-api.linearb.io/api/v2/pm/integrations/{integration_id}/entities/{entity_type}
Path parameters
| Parameter name | Value | Description |
|---|---|---|
| integration_id | integer | The integration. |
| entity_type | string | Jira: boards, projects. Azure Boards: projects. |
Body parameters
| Parameter name | Value | Description |
|---|---|---|
| entities | array | 1 to 1000 entries of entity_provider_id + is_selected_for_collection (true selects, false deselects). |
{
"entities": [
{"entity_provider_id": "109", "is_selected_for_collection": true},
{"entity_provider_id": "332", "is_selected_for_collection": false}
]
}
Responses
200 - At least one entry was applied. Valid entries apply even when others are rejected.
{
"integration_id": 1001,
"type": "boards",
"applied": [{"entity_provider_id": "109", "is_selected_for_collection": true}],
"rejected": [
{"entity_provider_id": "332", "is_selected_for_collection": false, "code": "entity_in_use",
"message": "332 is still in use and was left selected",
"used_by": {"teams": [{"id": 4413, "name": "Platform"}], "projects": []}}
]
}
400 - Nothing was applied (same body), a bad request, or the integration is read-only (still being connected, inactive or being removed)
403 - Forbidden, or the selection would exceed your organization's board / project limit (nothing is written)
404 - Not Found
| Rejection code | Meaning |
|---|---|
entity_not_found | No such entity on that integration. |
entity_not_reachable | The provider no longer exposes it, so it cannot be selected. Being unreachable never blocks a deselect. |
entity_in_use | Team scopes or projects still use it (used_by lists them). Remove it from those first. |
used_by_unavailable | Dependents could not be checked, so the deselect was refused. Retry. |
duplicate_entity | The same id appears more than once in the request. Both entries are refused. |
A newly selected board or project is collected on the next scheduled run, usually within the hour.
Get Team PM Scope
Reads what a team is scoped to, one item per integration. Same as Team Settings > Project Management in the app.
HTTP request
GET https://public-api.linearb.io/api/v1/pm/config/teams/{team_id}/scope
Path parameters
| Parameter name | Value | Description |
|---|---|---|
| team_id | integer | The team. |
Query parameters
| Parameter name | Value | Description |
|---|---|---|
| integration_ids | string | Comma-separated integration ids, up to 50. Omitted = all your PM integrations that are not deleted. |
Responses
200 - Successful Response
{
"team_id": 4412,
"team_name": "Payments",
"items": [
{
"integration_id": 1001, "provider": "jira", "integration_name": "Jira",
"scope": {"boards": [{"entity_provider_id": "109", "name": "Payments Scrum Board"}],
"epics": [], "labels": [], "fields": []},
"methodology": "Scrum"
},
{
"integration_id": 1002, "provider": "azure_boards", "integration_name": "Azure Boards",
"scope": {"project_team_areas": [
{"project": {"entity_provider_id": "9d09f4a3-6b23-46e3-8c9f-559d8e016ef5", "name": "Payments"},
"team": {"entity_provider_id": "f8732cf3-4aab-4bb4-a5e8-7a8099076109", "name": "Payments Team"},
"areas": [{"entity_provider_id": "395", "name": "Payments\\Backend"}]}]},
"methodology": "Kanban"
}
]
}
- Jira scope keys:
boards,epics,labels,fields. Azure Boards scope key:project_team_areas. "scope": {}means the team is not scoped on that integration, so it sees everything the integration collects.methodologyisScrumorKanban.
403 - Forbidden
404 - Not Found (the team, or an integration id, is not in your organization)
Write Team PM Scopes
Writes the PM scope of one or more teams.
PATCH(Update Team PM Scope Keys) writes the keys you send and leaves every other key as it is. Itsmodequery parameter says what happens to each key you send:mode=merge(the default): the list you send replaces that key's list. A key sent as[]is cleared.mode=add: the entries you send are added to that key's list. Entries already there are kept, nothing is removed, and a key sent as[]changes nothing.
POST(Replace Team PM Scopes) replaces each (team, integration) scope you name. Every item must name at least one scope key; to clear a whole scope, use Clear a Team PM Scope.
Scopes you do not name are never touched.
HTTP request
PATCH https://public-api.linearb.io/api/v1/pm/config/teams/scope?mode={merge|add}
POST https://public-api.linearb.io/api/v1/pm/config/teams/scope
Query parameters
| Parameter name | Value | Description |
|---|---|---|
| mode | string | PATCH only. merge or add. (Default: merge) |
Body parameters
| Parameter name | Value | Description |
|---|---|---|
| teams | array | Each entry: team_id and items, one per integration: integration_id, scope (the keys from Get Team PM Scope, in the shapes below; optional on PATCH, where omitted = no keys change; required on POST, with at least one key), and optional methodology (Scrum / Kanban). |
{
"teams": [
{"team_id": 4412, "items": [
{"integration_id": 1001, "scope": {"boards": [{"entity_provider_id": "109"}]}, "methodology": "Scrum"},
{"integration_id": 1002, "scope": {"project_team_areas": [
{"project": {"entity_provider_id": "9d09f4a3-6b23-46e3-8c9f-559d8e016ef5"},
"team": {"entity_provider_id": "f8732cf3-4aab-4bb4-a5e8-7a8099076109"},
"areas": [{"entity_provider_id": "395"}]}]}}
]}
]
}
Scope key shapes:
boards,epics:{"entity_provider_id": "109"}labels:{"name": "urgent"}- a label's name is its idfields:{"entity_provider_id": "customfield_10010", "value": ["Payments", "Billing"]}project_team_areas:{"project": {"entity_provider_id": "..."}, "team": {"entity_provider_id": "..."}, "areas": [{"entity_provider_id": "..."}]}
For example, a team scoped to boards 101 and 102 on integration 1001, sent {"integration_id": 1001, "scope": {"boards": [{"entity_provider_id": "109"}]}}:
- with
PATCH(orPATCH ?mode=merge) ends up on board109only; - with
PATCH ?mode=addends up on boards101,102and109.
Rules:
- Fields that Get Team PM Scope returns but a write does not take (
team_name,provider,integration_name, thenameof a board, project, team or area, an epic'sprovider_key) are accepted and ignored, so each item of a Get response can be sent back as is, under itsteam_idinteams. They are not needed: the shapes above are enough. A label'snameand a field'svalueare part of the scope, not display fields: keep them. WithPOST, leave out the items whosescopeis{}. - Up to 25 team-and-integration items and 1000 entities per call. Naming a team twice, or an integration twice under one team, is a
400. - Only the provider's scope keys are accepted: Jira
boards,epics,labels,fields; Azure Boardsproject_team_areas. Any other key is rejected withscope_key_not_writable. - Every entity must exist and be reachable on that integration. An Azure Boards
project_team_areasentry needs a project, a team in that project, and at least one area of that team. - Each (team, integration) item is applied or rejected as a whole.
- Emptying a team's Jira boards switches the team to Kanban, unless the same item sends
methodology. - A scope write also selects for collection what it names (Jira boards and epics, Azure projects), the same as saving in the app. That selection counts against your board / project limit, which is why a scope write can be rejected with
license_limit. Removing an entity from a scope does not deselect it: use Select PM Entities for Collection to stop collecting it.
Responses
200 - At least one item was applied
{
"applied": [{"team_id": 4412, "integration_id": 1001}],
"rejected": [
{"team_id": 4412, "integration_id": 1002, "status": 400, "code": "entity_not_found",
"message": "These do not exist on integration 1002 or are no longer reachable: areas 999"}
]
}
400 / 403 / 404 / 500 - Nothing was applied: the status all rejections share, or 400 if they differ (same body)
| Rejection code | Status | Meaning |
|---|---|---|
team_not_found | 404 | The team is not in your organization. |
integration_not_found | 404 | Not a live PM integration of your organization. |
provider_not_supported | 400 | The integration is not Jira or Azure Boards. |
integration_read_only | 400 | The integration is still being connected, inactive or being removed. The message says which. |
scope_key_not_writable | 400 | The key does not exist for that provider. |
invalid_scope | 400 | A malformed value, an entity named twice, or an Azure project / team / areas entry that does not match the provider. |
entity_not_found | 400 | The entity does not exist or is not reachable. |
license_limit | 403 | The selection the scope implies exceeds your board / project limit. |
write_failed | 500 | The write could not be completed. Retry. |
Clear a Team PM Scope Key
Clears one key of a team's scope on one integration. Same as a PATCH with that key set to [], with the same response.
HTTP request
DELETE https://public-api.linearb.io/api/v1/pm/config/teams/{team_id}/scope/{scope_key}?integration_id={integration_id}
Parameters
| Parameter name | Value | Description |
|---|---|---|
| team_id | integer | The team. |
| scope_key | string | Jira: boards, epics, labels, fields. Azure Boards: project_team_areas. |
| integration_id | integer | Required. The integration. |
Responses
200 - Successful Response
{"applied": [{"team_id": 4412, "integration_id": 1001}], "rejected": []}
400 / 403 / 404 / 500 - As for Write Team PM Scopes
Clear a Team PM Scope
Clears every key of a team's scope on one integration. The team's scopes on other integrations are not touched. On Jira this also switches the team to Kanban. A team that has no scope on that integration gets 200 and nothing changes.
HTTP request
DELETE https://public-api.linearb.io/api/v1/pm/config/teams/{team_id}/scope?integration_id={integration_id}
Parameters
| Parameter name | Value | Description |
|---|---|---|
| team_id | integer | The team. |
| integration_id | integer | Required. The integration. |
Responses
200 - Successful Response
{"applied": [{"team_id": 4412, "integration_id": 1001}], "rejected": []}
400 / 403 / 404 / 500 - As for Write Team PM Scopes
Errors and auditing
- A request the endpoint cannot accept returns
400: malformed input, or any query parameter or body field the endpoint does not know. Misspelled fields are refused, never ignored. - In a write, a problem with one entry or (team, integration) item does not fail the request: that entry comes back under
rejectedwith its owncode, and the rest is applied. - A query parameter given more than once returns
400. Send each parameter once, with several values comma-separated. - A team or integration that is not in your organization returns
404, never an empty list. - Every change made through these endpoints is recorded in your organization's audit log, like a change made in the app. See Audit Log.
Error responses
An error comes back in one of three shapes, so check the body as well as the status:
-
Nothing applied (the write endpoints): every entry was rejected, each with its own
codeandmessage.{"applied": [], "rejected": [{"team_id": 4412, "integration_id": 1001, "status": 400, "code": "entity_not_found", "message": "These do not exist on integration 1001 or are no longer reachable: boards 999"}]} -
Refused request: a message.
{"detail": "Unsupported entity type 'sprints'; valid types - Azure Boards: areas, projects, teams; Jira: boards, epics, fields, labels, projects"} -
Invalid request (a missing, malformed or unknown parameter or field): a list of validation errors.
{"detail": [{"type": "missing", "loc": ["query", "integration_id"], "msg": "Field required"}]}
A missing or invalid API key returns 403. A 500 means something failed on our side; retry.