> For the complete documentation index, see [llms.txt](https://docs.nullify.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nullify.ai/api-reference/api-reference/manager/action-items.md).

# Action items and escalations

Action items are the questions and decisions Manager hands to people: assigning an owner to a repository, mapping a git identity to a chat account, escalating a finding, or answering a question about your environment. This page covers listing and resolving them, nudging people, and the classifications that stop Manager asking about the same identity again.

Every operation takes the tenant's provider scope as query parameters, such as `githubOwnerId`.

Action items are tenant-wide operator data. When role-based access control is enforced for the tenant, callers whose role is limited to specific teams receive 403 ("operator access is unavailable for team-scoped roles") from these operations and from [Chat](/api-reference/api-reference/manager/chat.md).

Action items have a `kind` (`ESCALATED_FINDING`, `TACIT_KNOWLEDGE`, `UNMAPPED_USER`, `UNASSIGNED_TEAM`, `CONTEXT_CLARIFICATION`, `STRATEGY_PROPOSAL`, `CAMPAIGN_PROPOSAL`) and a `status` (`OPEN`, `RESOLVING`, `COMPLETED`, `DISMISSED`). The `resolutionMode` says how an item can be resolved: `CHAT` means only the Operator conversation, while `WIDGET_TEAM_PICKER` and `WIDGET_USER_MAPPING` have the structured endpoints below. The proposal kinds are notifications that a decision is waiting. Resolving or dismissing them here does not decide the strategy or campaign. Use the [decision endpoints](/api-reference/api-reference/manager.md#approvals-and-decisions).

## Reading action items

### List action items

Returns action items, filtered by `status`, `kind`, `teamId`, `unassignedOnly` (only items routed to central security) or a linked finding. `findingId` must be paired with `findingType`. An invalid filter value returns 400. Pages use `page` and `pageSize` (default 20).

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Summarize action items

Returns counts by status, kind and team, plus `total`, `totalOpen`, `totalStalled` and `unrouted`. An unrouted item is one the follow-up pass found no route for, such as no connected chat platform and no central channel. Zero unrouted is not the same as zero open.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/summary" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Get an action item

Returns one item with its linked findings, any still-open linked pull requests, the resolved git identity for user-mapping items, and the connected chat platform. Returns 404 for an unknown id or another tenant's item.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Get action item messages

Returns the conversation history for an item's chat, newest window first, in chronological order, with `page` and `pageSize` (default 100). `hasMore` says whether older messages exist. An item with no conversation yet returns an empty list, not 404. New messages arrive over the chat WebSocket rather than by polling this call.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}/messages" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Get or create an action item chat

Returns the item's Operator chat session id, creating the binding on the first call, so it is safe to repeat. The call needs a user identity, and returns 400 for an item that is already completed or dismissed. Use the returned `chatId` with the [Chat](/api-reference/api-reference/manager/chat.md) operations. Requires finding write access.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}/chat" method="put" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Routing and cleanup

### Change an action item's team

Reassigns the item's team with `teamId`. An empty string is rejected; send `null` to route the item to central security. Returns 400 for an unknown team or an item that is already completed or dismissed. The only field you can change this way is the team; status changes go through the operations below. Requires finding write access.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}" method="patch" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Delete an action item

Soft-deletes an item. It is housekeeping and is different from a dismissal. A dismissal that was recorded as decided cannot be deleted; reopen the item or revoke the classification instead. Requires team management permission.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}" method="delete" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Resolving action items

These operations resolve an item and record who did so. Status changes made by automation cannot override a person's decision: automation cannot make a decided dismissal, and cannot reopen an item that a person decided. Where an item is mid-resolution the call returns 409 and you should retry shortly.

### Assign a team to an item

Resolves an `UNASSIGNED_TEAM` item by assigning `teamId` as the owning team of every finding linked to the item, then completes it. Returns 400 unless the item's resolution mode is `WIDGET_TEAM_PICKER` or if the item has no linked findings. Repeating the call on an item a person already completed returns that item; an item Nullify resolved automatically returns 409. Requires finding write access.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}/assign-team" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Assign a team to a repository

Resolves an `UNASSIGNED_TEAM` item by making `teamId` the owner of the item's whole repository. The team becomes the repository's only manual code owner and survives every sync. The item completes as decided. Only a dashboard user or the operator may call it; automation is refused with 403. Returns 400 unless the resolution mode is `WIDGET_TEAM_PICKER`. Requires team management permission.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}/assign-repo" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Map a user

Resolves an `UNMAPPED_USER` item. Send exactly one of `messageUserId` (the chat user to map the git identity to; the provider is taken from the tenant's chat platform) or `serviceAccount: true`; sending both or neither returns 400. Returns 400 unless the item is a user-mapping item. Returns 409 and leaves the item open when the chat account was not stored: it was rejected earlier for this git user, the mapping already holds a different one, or another git user holds it. Requires finding write and user management permissions.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}/map-user" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Dismiss an action item

Moves an `OPEN` item to `DISMISSED`. `reason` is required (up to 500 characters). `disposition` is `not_now` (the default, and Manager asks again after a cooldown) or `decided` (Manager does not ask again about the same subject until someone reopens it). Only a person or the operator can record `decided`; automation gets 403. On an `UNMAPPED_USER` item, `classify` (`service_account` or `no_chat_account`) also records the identity's classification, and both that and a `decided` dismissal of such an item need user management permission. Dismissal is recoverable with [Reopen an action item](#reopen-an-action-item).

```bash
curl -s -X POST \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{"reason": "Owned by the platform team, tracked elsewhere", "disposition": "decided"}' \
  'https://api.<TENANT>.nullify.ai/manager/action-items/01J.../dismiss?githubOwnerId=1234'
```

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}/dismiss" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Reopen an action item

Returns an item to `OPEN` with a required `reason`. It accepts a dismissed item, or a completed item that Nullify resolved automatically. A person or the operator can also reopen a completed, decided repository assignment; other human completions are final. An `UNMAPPED_USER` item whose identity is classified is refused with 400, and you [revoke the classification](#revoke-an-identity-classification) instead. Automation cannot reopen an item a person decided, and reopening a decided user-mapping item needs user management permission. Returns 409 when an active duplicate of the item already exists.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}/reopen" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Nudges

### List escalation recipients

Returns the chat accounts in the tenant that are mapped to people and eligible to receive a manual nudge. Use their `id` as `recipientUserId` below. Requires finding write access.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/escalation-recipients" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Nudge an escalation

Sends another direct message for an open escalation. Optionally set `recipientUserId` and a custom `message` of up to 4,000 characters. The response has `sent` to say whether a message went out. Returns 400 when the item is not open, when no active chat account is mapped, when direct messages are disabled for the tenant (see [ground rules](/api-reference/api-reference/manager/escalations-and-config.md#ground-rules)), or when no Slack or Teams connection exists. Returns 409 if the escalation was nudged recently, or is being resolved; wait and try again. Requires finding write access.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/action-items/{actionItemId}/nudge" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Preview a fix pull request nudge

Shows who a reviewer nudge on a fix pull request would reach and the exact message, before you send it. The response lists candidates with whether each is `available`, the message `variant`, `sendsLeft` (the direct messages the pull request can still receive in the 30-day window across all nudges) and, when sending is not possible, a `disabledReason` such as `not_open` or `cap_reached`. `recordId` is the fix pull request record's id. Only open GitHub pull requests can be nudged. Requires finding write access.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/fix-prs/{recordId}/nudge" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Nudge fix pull request reviewers

Sends a governed direct message asking a fix pull request's reviewers to review it. Without a body it goes to the default reviewers; set `recipientUserIds` (up to 10 chat user ids) to send to specific people. The response gives an outcome per recipient: `sent`, `already_nudged`, `held_weekly_limit`, `failed` or `cap_reached`, so check each rather than the status code. Returns 429 once the pull request has used its nudges for the 30-day window and 409 if a nudge is already being sent. Requires finding write access.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/fix-prs/{recordId}/nudge" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

## Git identity classifications

A classification is a durable decision that a git identity is a service account or has no chat account, so Manager stops asking who it is. Classifying and revoking need an administrator, or the operator.

### List identity classifications

Returns classifications, newest first. Filter with `decision` (`service_account` or `no_chat_account`); omit it to list both.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/identity-classifications" method="get" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Classify an identity

Records `decision` for an identity given by `provider` (GitHub, GitLab, Azure or Bitbucket) and `providerUserId`, which is the provider's id for the user and not the login. An optional `reason` up to 500 characters is stored. It closes the identity's live `UNMAPPED_USER` item as decided, so the question is not asked again. Undo it with [Revoke an identity classification](#revoke-an-identity-classification).

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/identity-classifications" method="post" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}

### Revoke an identity classification

Removes the classification identified by the `provider` and `providerUserId` in the path, with an optional `reason` query parameter for the audit record. It reopens the identity's latest `UNMAPPED_USER` item and returns its id as `reopenedActionItemId`; when nothing needed reopening that field is absent, and Manager resumes asking in its daily sweep either way. Returns 404 when there is no such classification.

{% openapi src="/files/1NgvLK12PRq7RFdn97yd" path="/manager/identity-classifications/{provider}/{providerUserId}" method="delete" %}
[nullify-openapi-bundle.yaml](https://3946391995-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FId2OtLCL6O6V3XSRYxtr%2Fuploads%2Fgit-blob-26233c6743978bfec0535ad8febb4918da4bb6e4%2Fnullify-openapi-bundle.yaml?alt=media)
{% endopenapi %}
