# AWS SNS alerts

Source: https://docs.coderhelm.com/api/reference/webhooks/receive-sns-alert

`POST /webhooks/alerts/sns`

Subscribe CoderHelm to an SNS topic with an HTTPS subscription to this address and add the topic under Alert routes in the dashboard. Every message's SNS signature is checked (signature versions 1 and 2) and the signing certificate must come from SNS. The subscription is confirmed automatically once the topic has an enabled route; messages from topics without one are accepted and ignored. A message that matches one of the route's rules becomes a run that opens a pull request.

## Authentication

Verified by the request itself (see the description above). See [Webhooks](https://docs.coderhelm.com/api/webhooks).

## Request body

`application/json`: The SNS message.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `Message` | string | yes | The message: a CloudWatch alarm, an AWS Chatbot custom notification, an EventBridge event (as JSON text) or plain text. |
| `MessageId` | string | yes | SNS's id for the message. |
| `Signature` | string | yes | SNS's signature over the message's fields. |
| `SignatureVersion` | string | yes | `1` (SHA1) or `2` (SHA256). |
| `SigningCertURL` | string | yes | The certificate that signed it; must be served by SNS. |
| `Subject` | string or null | no | The subject, when the publisher set one. |
| `SubscribeURL` | string or null | no | For a subscription confirmation: the address CoderHelm visits to confirm. |
| `Timestamp` | string | yes | When SNS sent it. |
| `TopicArn` | string | yes | The topic. It must have an enabled alert route in the dashboard. |
| `Type` | string | yes | `SubscriptionConfirmation`, `Notification` or `UnsubscribeConfirmation`. |

## Responses

### 200

Accepted.

### 400

Not an SNS message.

### 403

The SNS signature did not verify.

## Example request

cURL:

```bash
curl -X POST 'https://api.coderhelm.com/webhooks/alerts/sns' \
  -H 'Content-Type: application/json' \
  -d '{
  "Message": "{\"AlarmName\":\"api-5xx\",\"NewStateValue\":\"ALARM\"}",
  "MessageId": "6c3f7c6e-2f4b-5b8e-9b0e-1f0a2b3c4d5e",
  "Signature": "EXAMPLE...",
  "SignatureVersion": "2",
  "SigningCertURL": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000.pem",
  "Subject": "ALARM: \"api-5xx\" in US East (N. Virginia)",
  "Timestamp": "2026-10-22T14:00:00.000Z",
  "TopicArn": "arn:aws:sns:us-east-1:123456789012:prod-alarms",
  "Type": "Notification"
}'
```

TypeScript:

```ts
const res = await fetch("https://api.coderhelm.com/webhooks/alerts/sns", {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "Message": "{\"AlarmName\":\"api-5xx\",\"NewStateValue\":\"ALARM\"}",
      "MessageId": "6c3f7c6e-2f4b-5b8e-9b0e-1f0a2b3c4d5e",
      "Signature": "EXAMPLE...",
      "SignatureVersion": "2",
      "SigningCertURL": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000.pem",
      "Subject": "ALARM: \"api-5xx\" in US East (N. Virginia)",
      "Timestamp": "2026-10-22T14:00:00.000Z",
      "TopicArn": "arn:aws:sns:us-east-1:123456789012:prod-alarms",
      "Type": "Notification"
    }),
});
if (!res.ok) {
  const { error, code } = await res.json();
  throw new Error(`${res.status} ${code}: ${error}`);
}
const data = await res.json();
```

Python:

```python
import requests

body = {
    "Message": "{\"AlarmName\":\"api-5xx\",\"NewStateValue\":\"ALARM\"}",
    "MessageId": "6c3f7c6e-2f4b-5b8e-9b0e-1f0a2b3c4d5e",
    "Signature": "EXAMPLE...",
    "SignatureVersion": "2",
    "SigningCertURL": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000.pem",
    "Subject": "ALARM: \"api-5xx\" in US East (N. Virginia)",
    "Timestamp": "2026-10-22T14:00:00.000Z",
    "TopicArn": "arn:aws:sns:us-east-1:123456789012:prod-alarms",
    "Type": "Notification",
}
res = requests.request("POST", "https://api.coderhelm.com/webhooks/alerts/sns", json=body)
if not res.ok:
    raise RuntimeError(f"{res.status_code}: {res.json().get('error')}")
data = res.json()
```
