---
title: "Assign Incident Roles"
description: "Sets the holder of an incident role (commander, tech lead, comms, assignee), or adds an extra responder to an Incident Management incident, optionally paging them."
---

An incident has four roles: `commander`, `tech_lead`, `comms` and `assignee`. Two endpoints manage who holds them:

- [Assign a role](#assign-a-role) sets the **single** holder of a role and replaces whoever held it before.
- [Add a responder](#add-a-responder) adds **another** person to a role without removing anyone, and can start paging them.

Current role holders are listed in `assignments` of [Get Incident](/api/incident-management/get-incident). Every change is recorded on the incident timeline. To remove a role holder, use the `assign` action of [Bulk Update Incidents](/api/incident-management/bulk-update-incidents) with `userId: null`.

## Authentication

Any IM-eligible role (`admin`, `editor`, `responder`) or an organization-wide API token, see [Authentication](/api/incident-management#authentication). Incident Management must be enabled for the organization.

**Who can be assigned:** the person in `userId` must be a user of your organization. Unless you are an organization admin (an organization-wide API token counts as one), that person must also be a member of the incident's team.

## Assign a role

`POST /api/im/incidents/:id/assign`

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|--------------|
| `userId` | string | Yes | User ID of the new role holder. |
| `role` | string | Yes | One of `commander`, `tech_lead`, `comms`, `assignee`. |

### Example (cURL)

```bash
curl -X POST "$BASE_URL/api/im/incidents/42/assign" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "userId": "MFcTjWmYq2LpzR8vK1sXo", "role": "commander" }'
```

### Response

`200 OK`: the new assignment.

```json
{
  "id": 12,
  "incidentId": 42,
  "userId": "MFcTjWmYq2LpzR8vK1sXo",
  "role": "commander",
  "createdAt": "2026-07-17T09:15:00.000Z",
  "user": {
    "name": "Grace Hopper",
    "email": "grace@example.com"
  }
}
```

`user.email` is only filled for an organization admin (and therefore a normal organization-wide API token); for every other role it is `null`.

### Common errors

- `401 Unauthorized` when not authenticated
- `403 Forbidden` (`customerScopedTokenForbidden`) when using a customer-scoped token
- `403 Forbidden` (`imAccessDenied`) when the session user has no IM-eligible role
- `403 Forbidden` (`imNotEnabled`) when Incident Management is not enabled for the organization
- `400 Bad Request` (`invalidRequestBody`) when `:id` is not a positive integer, `role` is missing or unknown, or `userId` is missing or blank
- `404 Not Found` (`imIncidentNotFound`) when the incident does not exist, or belongs to another organization
- `422 Unprocessable Entity` (`invalidUserId`) when `userId` does not exist or is not a user of your organization
- `422 Unprocessable Entity` (`imIncidentAssigneeNotOnTeam`) when you are not an organization admin and `userId` is not a member of the incident's team

## Add a responder

`POST /api/im/incidents/:id/add-responder`

Loops in an additional person, for example a specialist the escalation tiers would never reach. With `notify: true` that person's paging chain starts immediately, at the incident's current tier, with the urgency of the incident's severity.

Adding a responder is restricted to the incident's team: you must be a member of the incident's team or an organization admin. With `notify: true` you must be a **team admin** of the incident's team or an organization admin. An organization-wide API token passes both as an organization admin.

### Request Body

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `userId` | string | Yes | | User ID of the responder. |
| `role` | string | Yes | | One of `commander`, `tech_lead`, `comms`, `assignee`. |
| `notify` | boolean | No | `false` | `true` starts paging this person right away. |

### Example (cURL)

```bash
curl -X POST "$BASE_URL/api/im/incidents/42/add-responder" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "userId": "Zx81KpLmQr7TbVn2WcYdE", "role": "tech_lead", "notify": true }'
```

### Response

`200 OK`: the new assignment, plus whether paging was started.

```json
{
  "id": 13,
  "incidentId": 42,
  "userId": "Zx81KpLmQr7TbVn2WcYdE",
  "role": "tech_lead",
  "createdAt": "2026-07-17T09:30:00.000Z",
  "user": {
    "name": "Ada Lovelace",
    "email": "ada@example.com"
  },
  "notifyStarted": true
}
```

`notifyStarted` echoes `notify`. Paging is queued best-effort after the assignment is saved; if queuing fails, the assignment still stands and the failure is only logged server-side.

### Common errors

- `401 Unauthorized` when not authenticated
- `403 Forbidden` (`customerScopedTokenForbidden`) when using a customer-scoped token
- `403 Forbidden` (`imAccessDenied`) when the session user has no IM-eligible role
- `403 Forbidden` (`imNotEnabled`) when Incident Management is not enabled for the organization
- `403 Forbidden` (`imTeamMembershipRequired`) when you are neither a member of the incident's team nor an organization admin
- `403 Forbidden` (`imTeamAdminRequired`) when `notify` is `true` and you are neither a team admin of the incident's team nor an organization admin
- `400 Bad Request` (`invalidRequestBody`) when `:id` is not a positive integer, `role` is missing or unknown, or `userId` is missing or blank
- `404 Not Found` (`imIncidentNotFound`) when the incident does not exist, or belongs to another organization
- `422 Unprocessable Entity` (`invalidUserId`) when `userId` does not exist or is not a user of your organization
- `422 Unprocessable Entity` (`imIncidentAssigneeNotOnTeam`) when you are not an organization admin and `userId` is not a member of the incident's team
- `409 Conflict` (`imIncidentAssignmentExists`) when this person already holds this role on the incident
