> ## Documentation Index
> Fetch the complete documentation index at: https://docs.incident.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Advanced settings

> Covers advanced settings, such as telling your systems who made each request.

## Caller identity

Turn on **Share caller identity** and each call to a data source tells your server who made it, instead of every call looking like incident.io. Your server can then:

* Apply granular access controls based on the identity of the caller.
* Rate-limit each caller separately.
* Limit what automated callers, such as investigations, can do.
* Record who made each call, for your own audits and operational controls.

It's available for MCP and HTTP [connectors](https://docs.incident.io/nexus/extensions/connectors.md) and some telemetry sources, and it's off until you turn it on.

### Turning it on

Open the data source's settings and turn on **Share caller identity**. You need the **Manage Nexus sources** permission for the data source. Turning it on or off is recorded in your [audit log](https://docs.incident.io/admin/audit-logs.md).

### Which calls carry it

Every call to the data source carries it, from everywhere a call can be made: Investigations, Chat, workflows, and via the incident.io MCP.

### Headers

Each call carries two headers. They're always sent together.

```http theme={null}
X-Incident-Actor: user:01HQ4T7W2K9M5R8V3C6N1D0XZB
X-Incident-Actor-Assertion: eyJhbGciOiJFUzI1NiIsImtpZCI6ImNhbGxlci1pZGVudGl0eS0yMDI2LTEwIiwidHlwIjoiSldUIn0...
```

`X-Incident-Actor` names the caller as `<type>:<id>`. It's the same actor as on the call's entry in your audit log, so you can match a request to its entry.

| Caller | Header | Example |
| - | - | - |
| A user, from the dashboard, Chat, the incident.io MCP or an API key | `user:<user ID>` | `user:01HQ4T7W2K9M5R8V3C6N1D0XZB` |
| A workflow, including one that runs an agent | `workflow:<workflow ID>` | `workflow:01HB2Y7N5Q0C4WJ1T8F6R3KZPV` |
| An API key with no user behind it | `api_key:<API key ID>` | `api_key:01HC8M3V2R5X9D7K0B4N6T1QJS` |
| incident.io acting on its own, such as an investigation | `system:<name>` | `system:incident_investigations` |

`X-Incident-Actor-Assertion` is a signed JWT that proves the header. It's valid for 60 seconds.

### The assertion

The assertion is signed with ES256. Its header names the key that signed it:

```json theme={null}
{ "alg": "ES256", "kid": "caller-identity-2026-10", "typ": "JWT" }
```

Its claims:

| Claim | Type | Value |
| - | - | - |
| `iss` | string | `https://app.incident.io`. Our public keys are at `<iss>/.well-known/jwks.json`. |
| `sub` | string | The caller. It's the same as `X-Incident-Actor`. |
| `aud` | array of strings | Your server's origin, its scheme and host, such as `["https://mcp.example.com"]`. It holds one value, so an assertion for one data source is no good at another. |
| `exp` | number | When it expires, 60 seconds after `iat`. All times are Unix seconds. |
| `nbf` | number | When it becomes valid, 30 seconds before `iat`. |
| `iat` | number | When we signed it. |
| `jti` | string | A new ID (a ULID) for each assertion. |
| `via` | string | What the caller acted through, as `<kind>:<id>`. Only present when the caller acted through something. |
| `org` | string | Your incident.io organization ID. |
| `ctx` | object | The work the call is part of (see below). |

`ctx` uses the same keys as the call's audit log entry. We leave out a key we don't know rather than send it empty:

| Key | Value |
| - | - |
| `surface` | Where the call came from. Always present. |
| `incident_id` | The incident the call was made for. |
| `investigation_id` | The investigation that made the call. |
| `telemetry_query_id` | The ID we store the call under. The audit log entry carries the same ID. |
| `approval_id` | The approval request the call carries out, when someone had to approve it first. |
| `approved_by` | The ID of the user who approved it. |

Here's a decoded assertion for a call from Chat that needed approval:

```json theme={null}
{
  "iss": "https://app.incident.io",
  "sub": "user:01HQ4T7W2K9M5R8V3C6N1D0XZB",
  "aud": ["https://mcp.example.com"],
  "exp": 1793361660,
  "nbf": 1793361570,
  "iat": 1793361600,
  "jti": "01JBX6Q4M2Z8R1V7K3T9N5C0WD",
  "via": "integration:incident_copilot",
  "org": "01GZ8P3M6R1T9W4K7C2V5N0QHJ",
  "ctx": {
    "surface": "chat",
    "incident_id": "01JBX5ZK8T2W6N4C9R0V3M7QHD",
    "telemetry_query_id": "01JBX6Q4KZ3P0D8T5W1N7R2C6V",
    "approval_id": "01JBX6NF9V4K2T7R0W5C3M8QZP",
    "approved_by": "01HQ4T7W2K9M5R8V3C6N1D0XZB"
  }
}
```

### Verifying the assertion

Our public keys are published as a JSON Web Key Set at `https://app.incident.io/.well-known/jwks.json`. The endpoint needs no authentication, and responses can be cached for 5 minutes. Each key is a P-256 key with `alg` `ES256` and `use` `sig`.

Pick the key by the `kid` in the assertion's header. Don't hard-code a key or a `kid`, because keys change over time.
