# Tellagen API Reference

> Generated from the same canonical API contract as the human-readable reference at https://tellagen.com/api-reference.

Documentation contract: `sha256:898ee484330817a84c170e0e87bf24f27e62e5838635ee4c9daf6a7a3d704ce9`. This fingerprint identifies the generated documentation contract, not the API major version.

## Endpoint index

### Writable configuration

[Writable configuration Markdown export](https://tellagen.com/api-reference/configuration/markdown)

- [`GET /api/v1/configuration/workflow-statuses`](https://tellagen.com/api-reference/configuration#configuration-endpoint-get-api-v1-configuration-workflow-statuses) — List available workflow statuses
- [`GET /api/v1/configuration/severities`](https://tellagen.com/api-reference/configuration#configuration-endpoint-get-api-v1-configuration-severities) — List available severities
- [`GET /api/v1/configuration/service-tiers`](https://tellagen.com/api-reference/configuration#configuration-endpoint-get-api-v1-configuration-service-tiers) — List available service tiers

## Base URL

`https://{company}.api.tellagen.com/api/v1/`

Replace `{company}` with your company subdomain. Requests and JSON responses use `application/json` unless an endpoint documents an empty response.

## Authentication

Create an API token in **Settings > API keys** and send it as a Bearer token:

`Authorization: Bearer tllg_YOUR_TOKEN`

Tokens are shown only once when created. Grant only the scopes the client needs.

## Integration guides

- [Make your first request](https://tellagen.com/api-reference#first-request)
- [Build reliable requests](https://tellagen.com/api-reference#reliable-requests)
- [Filter and paginate collections](https://tellagen.com/api-reference/guides/pagination)
- [Create and move an incident through its workflow](https://tellagen.com/api-reference/guides/workflows)
- [Send custom-field values](https://tellagen.com/api-reference/guides/field-values)

## Versioning

All endpoints in this reference use `/api/v1` and are supported.

**Compatible changes.** Tellagen can add optional response fields or enum values. Ignore response fields that your client does not use.

**Breaking changes.** Tellagen uses a new major version for incompatible changes.

**Deprecated endpoints.** Tellagen marks an endpoint deprecated at least 180 days before removal. Deprecated responses identify the replacement endpoint.

## Scopes

| Scope | Description |
| --- | --- |
| `incidents:read` | List and retrieve incidents, and discover writable workflow statuses and severities |
| `incidents:write` | Create and update incidents and timeline events. Requires an active responder seat for the key owner. |
| `slack_context:read` | Read Slack context collected for incident investigation |
| `services:read` | List and retrieve services, and discover writable service tiers |
| `services:write` | Create, update, and archive services. Requires an active responder seat and the manage_settings role permission. |
| `teams:read` | List and retrieve teams and members |
| `teams:write` | Create, update, and archive teams; manage members. Requires an active responder seat and the manage_teams role permission. |
| `custom_fields:read` | List and retrieve custom field definitions and values |
| `custom_fields:write` | Create, update, and archive custom fields; set incident field values. Definition changes require the manage_settings role permission. Incident value changes require an active responder seat. |

## Prerequisite definitions

- **Active responder seat** (`active_responder`): The API key owner must have an active responder seat.
- **Manage workspace settings** (`manage_settings`): The API key owner must have the manage_settings role permission.
- **Manage teams** (`manage_teams`): The API key owner must have the manage_teams role permission.
- **Incident is not archived** (`mutable_incident`): The incident must not be archived. Workflow-state restrictions are described by each operation.
- **Linked Slack channel** (`slack_channel`): The incident must have a linked Slack channel.

## Errors

Errors always include a stable `code` and a human-readable `message`. They can also include `field`, `details`, and `request_id`.

You can send `X-Request-ID` with a request. If you omit it, the API generates one. The response header and error body return the same value.

### Missing scope (403)

```json
{
  "code": "missing_scope",
  "message": "insufficient scope: incidents:write required",
  "details": {
    "required_scope": "incidents:write"
  },
  "request_id": "01JEXAMPLE8R4N5W6Y7Z"
}
```

### Stale resource version (412)

```json
{
  "code": "precondition_failed",
  "message": "the resource changed; fetch it again and retry with the current resource version",
  "field": "If-Tellagen-Resource-Version",
  "request_id": "01JEXAMPLE8R4N5W6Y7Z"
}
```

### Rate limit (429)

```json
{
  "code": "rate_limited",
  "message": "rate limit exceeded",
  "details": {
    "retry_after_seconds": 1
  },
  "request_id": "01JEXAMPLE8R4N5W6Y7Z"
}
```

When you contact support, include the request ID, method, path, status, and time. Omit tokens and private request bodies.

| Code | Meaning | Next action | Retry |
| --- | --- | --- | --- |
| `authentication_required` | The request has no valid API token or session. | Send an active Bearer token for this workspace. Replace an expired or revoked key. | After correcting authentication. |
| `missing_scope` | The token lacks the scope named in details.required_scope. | Read details.required_scope. Ask a workspace manager for a replacement key with that scope. | After correcting access. |
| `responder_seat_required` | The key owner needs the seat named in details.required_seat. | Ask a workspace manager to review the key owner’s responder seat. | After correcting access. |
| `missing_role_permission` | The key owner lacks details.required_permission or one of details.required_roles. | Ask a workspace manager to review the owner’s role and the permission named in details. | After correcting access. |
| `permission_denied` | Access is denied without exposing private authorization state. | Verify the workspace, key owner, and resource access with a workspace manager. | After correcting access. |
| `invalid_resource_state` | The operation is not valid for the current resource state. | Read the current resource. Restore an archived resource or choose an operation allowed in its current state. | After reconciling state. |
| `invalid_relationship_state` | Restore requires a retained owner or parent relationship to identify an active resource. | Restore the retained parent or owning team before restoring this resource. | After correcting the relationship. |
| `duplicate_slug` | A team already uses the requested slug. | Read the existing team or choose a different slug. | After changing the request. |
| `invalid_json` | The request body is not one valid JSON document. | Send one valid JSON object with Content-Type: application/json. | After correcting the body. |
| `unknown_field` | The request contains an unsupported JSON property named in field. | Remove or correct the property named in field. Use the request schema, not the response schema. | After correcting the body. |
| `request_body_too_large` | The request body is larger than 1 MiB. | Reduce the body to 1 MiB or less. | After reducing the body. |
| `multiple_json_values` | The request body contains more than one JSON document. | Send one JSON document rather than concatenated documents. | After correcting the body. |
| `idempotency_key_reused` | The key was already used with different request content. | Recover the original request for this key. Use a new key only for a different intended operation. | Do not resend changed content with the same key. |
| `idempotency_in_progress` | An equal request with this key is still running. Retry later. | Wait for Retry-After, then resend the identical body with the same key. | After the indicated delay. |
| `idempotency_outcome_unknown` | An earlier request may have completed, but its result could not be stored. Do not retry it automatically. | Read the resource state and contact support with the request ID before deciding whether to create again. | Never retry automatically. |
| `precondition_required` | An API-key PATCH request omitted If-Tellagen-Resource-Version. | Read the resource, then send its Tellagen-Resource-Version as If-Tellagen-Resource-Version. | After adding the current version. |
| `invalid_precondition` | If-Tellagen-Resource-Version is not a positive integer. | Use the positive integer version returned for this resource. Do not use an ETag or a timestamp. | After correcting the header. |
| `precondition_failed` | The resource changed after the client read it. | Read the resource again. Reconcile your intended change with the current state before using its new version. | After reconciling the change. |
| `rate_limited` | Retry after details.retry_after_seconds or the Retry-After header. | Wait for Retry-After or details.retry_after_seconds. Limit concurrency across the workspace. | After the indicated delay, with the original idempotency key where supported. |
| `internal` | The server failed without exposing an internal error. | Keep the request ID. Read current state before retrying a write whose outcome is uncertain. | Retry reads with bounded backoff. Follow operation-specific rules for writes. |
| `invalid_slack_channel_name_request` | The channel-name request is invalid. | Use custom mode with name, or workspace_template mode without name. | After correcting the request. |
| `slack_not_configured` | The workspace has no usable Slack integration. | Ask a workspace manager to connect or repair Slack. | After repairing the integration. |
| `incident_slack_channel_missing` | The incident has no linked Slack channel. | Link a channel through the incident workspace before requesting a rename. | After linking a channel. |
| `slack_channel_not_found` | Slack cannot find the linked channel. | Verify the channel still exists and that the integration can access it. | After repairing channel access. |
| `slack_channel_name_taken` | Another Slack channel uses the requested name. | Choose another custom name or revise the workspace naming template. | After choosing an available name. |
| `invalid_idempotency_key` | The idempotency key has an invalid length or character. | Use 1–128 visible, non-space ASCII characters. A UUID is suitable. | After correcting the key. |

| Status | Meaning |
| --- | --- |
| `400` | Bad Request — invalid input or missing required fields |
| `401` | Unauthorized — missing or invalid token |
| `403` | Forbidden — insufficient scope or responder access |
| `404` | Not Found — resource does not exist |
| `409` | Conflict — resource state prevents the request |
| `412` | Precondition Failed — the supplied resource version is stale |
| `428` | Precondition Required — this operation needs If-Tellagen-Resource-Version |
| `429` | Too Many Requests — rate limit exceeded |
| `500` | Internal Server Error |

Authenticated requests share a workspace limit. Anonymous requests and failed authentication attempts use the trusted client IP. Responses include `X-RateLimit-Limit` and `X-RateLimit-Remaining`. A `429` response also includes `Retry-After`.

## Writable configuration

Lists the workspace-specific keys accepted by incident and service requests. These endpoints also identify the default status, severity, and service tier.

### `GET /api/v1/configuration/workflow-statuses`

**List available workflow statuses.** Returns the workflow statuses that incident requests can use. The response lists statuses in workflow order. Exactly one status has is_default set to true. If a create-incident request omits status, the API uses that status.

Required scope: `incidents:read`

Operation ID: `listWorkflowStatuses`
Contract: `supported`
Retry guidance: This operation is repeat-safe. Respect Retry-After and use bounded retries.
Prerequisites: None

#### Example request

Replace `{company}`, `<token>`, and any other placeholders with your values.

```bash
curl --request GET \
  --url 'https://{company}.api.tellagen.com/api/v1/configuration/workflow-statuses' \
  --header 'Authorization: Bearer <token>'
```

#### Success response

Status: `200 OK`

#### Response fields

Returned means the field is present when its parent object is present. A nullable field can contain null.

| Name | Type | Returned | Description |
| --- | --- | --- | --- |
| `workflow_statuses` | `object[]` | Always | The workflow statuses in configured workflow order. |
| `workflow_statuses[].key` | `string` | Always | A workflow-status key accepted by incident requests. |
| `workflow_statuses[].label` | `string` | Always | The status name shown to users. |
| `workflow_statuses[].order` | `integer` | Always | The zero-based position of the status in the workflow. Minimum: 0. |
| `workflow_statuses[].is_default` | `boolean` | Always | Identifies the default workflow status for new incidents. |
| `workflow_statuses[].is_terminal` | `boolean` | Always | Indicates whether this status ends the active incident workflow. |
| `workflow_statuses[].is_escalation_threshold` | `boolean` | Always | Indicates whether this status is the configured escalation threshold. |
| `workflow_statuses[].color` | `string` | Always | The color token used to display the status. |

Each entry contains a status key, label, display order, default flag, lifecycle flags, and color.

```json
{
  "workflow_statuses": [
    {
      "key": "open",
      "label": "Open",
      "order": 0,
      "is_default": true,
      "is_terminal": false,
      "is_escalation_threshold": true,
      "color": "ember"
    },
    {
      "key": "resolved",
      "label": "Resolved",
      "order": 1,
      "is_default": false,
      "is_terminal": true,
      "is_escalation_threshold": false,
      "color": "moss"
    }
  ]
}
```

#### Endpoint error responses

| Status | Meaning |
| --- | --- |
| `400` | The API rejected the request because its syntax or one of its values is invalid. |
| `401` | The request does not contain valid authentication. |
| `403` | Authentication succeeded, but the caller lacks the required API scope or workspace permission. |
| `404` | The requested resource does not exist or is not available to the caller. |
| `409` | The request conflicts with the current resource state. idempotency_key_reused means that the key belongs to different request content. idempotency_in_progress means that an identical request is still in progress. idempotency_outcome_unknown means that an earlier request may have completed, but its result could not be stored and must not be retried automatically. |
| `429` | The workspace exceeded an active request limit. |
| `500` | An internal server error prevented completion of the request. |

### `GET /api/v1/configuration/severities`

**List available severities.** Returns the severity levels that incident requests can use. The response lists severities from the highest score threshold to the lowest. Exactly one severity has is_default set to true. If a create-incident request omits severity, the API uses that severity.

Required scope: `incidents:read`

Operation ID: `listSeverities`
Contract: `supported`
Retry guidance: This operation is repeat-safe. Respect Retry-After and use bounded retries.
Prerequisites: None

#### Example request

Replace `{company}`, `<token>`, and any other placeholders with your values.

```bash
curl --request GET \
  --url 'https://{company}.api.tellagen.com/api/v1/configuration/severities' \
  --header 'Authorization: Bearer <token>'
```

#### Success response

Status: `200 OK`

#### Response fields

Returned means the field is present when its parent object is present. A nullable field can contain null.

| Name | Type | Returned | Description |
| --- | --- | --- | --- |
| `severities` | `object[]` | Always | The severity levels from the highest score threshold to the lowest. |
| `severities[].key` | `string` | Always | A severity key accepted by incident requests. |
| `severities[].label` | `string` | Always | The severity name shown to users. |
| `severities[].order` | `integer` | Always | The zero-based position of the severity in the response. Minimum: 0. |
| `severities[].is_default` | `boolean` | Always | Identifies the default severity for new incidents. |
| `severities[].min_score` | `number` | Always | The minimum calculated score for this severity. Minimum: 0. |
| `severities[].description` | `string` | Always | The workspace description of this severity. |
| `severities[].color` | `string` | Always | The color token used to display the severity. |

Each entry contains a severity key, label, display order, default flag, score threshold, description, and color.

```json
{
  "severities": [
    {
      "key": "sev1",
      "label": "SEV1",
      "order": 0,
      "is_default": false,
      "min_score": 300,
      "description": "Critical - complete outage",
      "color": "ember"
    },
    {
      "key": "sev2",
      "label": "SEV2",
      "order": 1,
      "is_default": true,
      "min_score": 150,
      "description": "Major - degraded experience",
      "color": "amber-500"
    }
  ]
}
```

#### Endpoint error responses

| Status | Meaning |
| --- | --- |
| `400` | The API rejected the request because its syntax or one of its values is invalid. |
| `401` | The request does not contain valid authentication. |
| `403` | Authentication succeeded, but the caller lacks the required API scope or workspace permission. |
| `404` | The requested resource does not exist or is not available to the caller. |
| `409` | The request conflicts with the current resource state. idempotency_key_reused means that the key belongs to different request content. idempotency_in_progress means that an identical request is still in progress. idempotency_outcome_unknown means that an earlier request may have completed, but its result could not be stored and must not be retried automatically. |
| `429` | The workspace exceeded an active request limit. |
| `500` | An internal server error prevented completion of the request. |

### `GET /api/v1/configuration/service-tiers`

**List available service tiers.** Returns the service tiers that service requests can use. The response lists tiers in configured rank order. Exactly one tier has is_default set to true. If a create-service request omits tier, the API uses that tier.

Required scope: `services:read`

Operation ID: `listServiceTiers`
Contract: `supported`
Retry guidance: This operation is repeat-safe. Respect Retry-After and use bounded retries.
Prerequisites: None

#### Example request

Replace `{company}`, `<token>`, and any other placeholders with your values.

```bash
curl --request GET \
  --url 'https://{company}.api.tellagen.com/api/v1/configuration/service-tiers' \
  --header 'Authorization: Bearer <token>'
```

#### Success response

Status: `200 OK`

#### Response fields

Returned means the field is present when its parent object is present. A nullable field can contain null.

| Name | Type | Returned | Description |
| --- | --- | --- | --- |
| `service_tiers` | `object[]` | Always | The service tiers in configured rank order. |
| `service_tiers[].key` | `string` | Always | A service-tier key accepted by service requests. |
| `service_tiers[].label` | `string` | Always | The tier name shown to users. |
| `service_tiers[].order` | `integer` | Always | The zero-based position of the tier in configured rank order. Minimum: 0. |
| `service_tiers[].is_default` | `boolean` | Always | Identifies the default tier for new services. |
| `service_tiers[].description` | `string` | Always | The workspace description of this service tier. |

Each entry contains a tier key, label, display order, default flag, and description.

```json
{
  "service_tiers": [
    {
      "key": "t0",
      "label": "T0 - Mission Critical",
      "order": 0,
      "is_default": false,
      "description": "Mission critical"
    },
    {
      "key": "t2",
      "label": "T2 - Important",
      "order": 2,
      "is_default": true,
      "description": "Important"
    }
  ]
}
```

#### Endpoint error responses

| Status | Meaning |
| --- | --- |
| `400` | The API rejected the request because its syntax or one of its values is invalid. |
| `401` | The request does not contain valid authentication. |
| `403` | Authentication succeeded, but the caller lacks the required API scope or workspace permission. |
| `404` | The requested resource does not exist or is not available to the caller. |
| `409` | The request conflicts with the current resource state. idempotency_key_reused means that the key belongs to different request content. idempotency_in_progress means that an identical request is still in progress. idempotency_outcome_unknown means that an earlier request may have completed, but its result could not be stored and must not be retried automatically. |
| `429` | The workspace exceeded an active request limit. |
| `500` | An internal server error prevented completion of the request. |
