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

# Post Incident Update

> Post a new update on an incident with explicit visibility — optionally transitioning status in the same call.

Posts a new update on an incident. The update may carry a message body, a status transition, or both — at least one is required. Updates are **append-only**; to correct a previous statement, [redact](./updates-redact) the original and post a new one.

## Visibility

`visibility` is required on every request — there is no default.

| Visibility | Renders on the public status page?                                                            | Body required? |
| ---------- | --------------------------------------------------------------------------------------------- | -------------- |
| `internal` | Only as a bare transition row when `statusChange` is set; the body is never exposed publicly. | No             |
| `public`   | Yes — the body is the message bubble customers read.                                          | Yes            |

Posting `public` is rejected with `no_public_surface` (`400`) when the incident has no published Status Page whose selected components overlap with the incident's affected components. Subscribe a Status Page to the affected components before publishing.

Resolved incidents are **terminal** — `POST` against a resolved incident returns `400 incident_resolved`. You may still [redact](./updates-redact) updates on a resolved incident.

## Path parameters

<ParamField path="id" type="string" required>
  The UUID of the incident.
</ParamField>

## Request body

<ParamField body="visibility" type="string" required>
  `internal` or `public`. No default — must be set explicitly.
</ParamField>

<ParamField body="body" type="string">
  Free-text message up to 10,000 characters. Required when `visibility` is
  `public`. Optional when `visibility` is `internal` — but at least one of
  `body` or `statusChange` must be set.
</ParamField>

<ParamField body="statusChange" type="string">
  Optional lifecycle transition. One of `investigating`, `identified`,
  `monitoring`, `resolved`. Must follow the existing sequence — see [Update
  Status](./update-status) for the rules. When set, the incident's `status`
  advances in the same write.
</ParamField>

## Response

Returns the created incident update.

<ResponseField name="data" type="object" required>
  <Expandable title="properties" defaultOpen>
    <ResponseField name="id" type="string" required>
      Server-generated ID of the update (UUID).
    </ResponseField>

    <ResponseField name="incidentId" type="string" required>
      Incident this update belongs to.
    </ResponseField>

    <ResponseField name="body" type="string or null" required>
      Update message. `null` when the update is a status-only internal update or has been redacted.
    </ResponseField>

    <ResponseField name="statusChange" type="string or null" required>
      Lifecycle status the incident transitioned to, or `null` if the update is body-only.
    </ResponseField>

    <ResponseField name="visibility" type="string" required>
      `internal` or `public`.
    </ResponseField>

    <ResponseField name="postedBy" type="object" required>
      The user who posted the update. `{ id, name }`.
    </ResponseField>

    <ResponseField name="postedAt" type="string" required>
      ISO 8601 timestamp.
    </ResponseField>

    <ResponseField name="redactedAt" type="string or null" required>
      ISO 8601 timestamp when the update was redacted, or `null`.
    </ResponseField>

    <ResponseField name="redactedBy" type="object or null" required>
      The user who redacted the update (`{ id, name }`), or `null`.
    </ResponseField>
  </Expandable>
</ResponseField>

## Error responses

| Status | Code                                      | Description                                                                                    |
| ------ | ----------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `400`  | `body_required_for_public`                | `visibility=public` was set but no `body` was provided.                                        |
| `400`  | `no_public_surface`                       | The incident has no published Status Page that covers its affected components. Cannot publish. |
| `400`  | `incident_resolved`                       | The incident is already `resolved`; no further updates are accepted (you may still redact).    |
| `400`  | `invalid_status_transition`               | `statusChange` does not follow the lifecycle sequence.                                         |
| `400`  | `update_must_carry_body_or_status_change` | Neither `body` nor `statusChange` was provided.                                                |
| `401`  | `not_authorized`                          | Missing or invalid credentials.                                                                |
| `404`  | `not_found`                               | No incident with the given ID exists in your organization.                                     |
| `422`  | —                                         | Request body failed validation (e.g. unknown `visibility`, body over 10,000 chars).            |
| `500`  | `server_error`                            | An unexpected error occurred on our side.                                                      |

<RequestExample>
  ```bash Post a public update theme={null}
  curl --request POST \
    --url "https://api.scaling.cloud/v1/incidents/YOUR_INCIDENT_ID/updates" \
    --header "Authorization: Bearer YOUR_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "body": "We have identified the cause as a misconfigured rate limit on the payment gateway. Working on a rollback now.",
      "statusChange": "identified",
      "visibility": "public"
    }'
  ```

  ```bash Post an internal note theme={null}
  curl --request POST \
    --url "https://api.scaling.cloud/v1/incidents/YOUR_INCIDENT_ID/updates" \
    --header "Authorization: Bearer YOUR_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "body": "Paging the payments lead — context in incident channel.",
      "visibility": "internal"
    }'
  ```

  ```bash Status-only internal transition theme={null}
  curl --request POST \
    --url "https://api.scaling.cloud/v1/incidents/YOUR_INCIDENT_ID/updates" \
    --header "Authorization: Bearer YOUR_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "statusChange": "monitoring",
      "visibility": "internal"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "id": "0193e1a2-3b4c-7890-abcd-ef1234567890",
      "incidentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "body": "We have identified the cause as a misconfigured rate limit on the payment gateway. Working on a rollback now.",
      "statusChange": "identified",
      "visibility": "public",
      "postedBy": { "id": "user_2b9a3d4e5f6g7h8j", "name": "Alice Chen" },
      "postedAt": "2025-04-07T09:14:00.000Z",
      "redactedAt": null,
      "redactedBy": null
    }
  }
  ```

  ```json 400 no_public_surface theme={null}
  {
    "statusCode": 400,
    "type": "invalid_request_error",
    "code": "no_public_surface",
    "requestId": "d3e4f5a6-b7c8-9012-defa-bc1234567890"
  }
  ```

  ```json 400 body_required_for_public theme={null}
  {
    "statusCode": 400,
    "type": "invalid_request_error",
    "code": "body_required_for_public",
    "requestId": "d3e4f5a6-b7c8-9012-defa-bc1234567890"
  }
  ```

  ```json 400 incident_resolved theme={null}
  {
    "statusCode": 400,
    "type": "invalid_request_error",
    "code": "incident_resolved",
    "requestId": "d3e4f5a6-b7c8-9012-defa-bc1234567890"
  }
  ```

  ```json 404 not_found theme={null}
  {
    "statusCode": 404,
    "type": "invalid_request_error",
    "code": "not_found",
    "requestId": "d3e4f5a6-b7c8-9012-defa-bc1234567890"
  }
  ```
</ResponseExample>

## End-to-end example

A typical "investigate → publish update → resolve" flow:

```bash theme={null}
# 1. Create the incident
curl -X POST "https://api.scaling.cloud/v1/incidents" \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{"title":"Payments elevated error rate","severity":"critical","leadScheduleId":"f47ac10b-58cc-4372-a567-0e02b2c3d479","componentIds":["6ba7b810-9dad-11d1-80b4-00c04fd430c8"]}'
# → { "data": { "id": "INC_ID", ... } }

# 2. Publish "we are investigating" to the status page
curl -X POST "https://api.scaling.cloud/v1/incidents/INC_ID/updates" \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{"body":"We are investigating elevated error rates on the Payments API.","visibility":"public"}'

# 3. Publish the resolution and transition to resolved in one call
curl -X POST "https://api.scaling.cloud/v1/incidents/INC_ID/updates" \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{"body":"Rolled back deploy v3.14.2. Error rates back to baseline.","statusChange":"resolved","visibility":"public"}'
```

<Note>
  This endpoint does not yet support client-supplied idempotency keys at the API
  layer. Retrying a transient `5xx` may create a duplicate update — guard your
  callers with their own dedupe key (e.g. cache the `id` from the first 200
  response) until end-to-end idempotency is exposed.
</Note>
