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

# Notification webhook payload

> Schema and signing for outbound deployment notification POSTs.

Slipway delivers deployment notifications to user-configured channels via HTTPS POST. Discord and Slack receive platform-native payloads; **generic webhook** channels receive the schema below.

## Request

* **Method**: `POST`
* **Content-Type**: `application/json`
* **User-Agent**: `slipway-notifier/1`
* **X-Slipway-Signature**: `sha256=<hex>` — present only when the channel has a signing secret configured (see [HMAC signing](#hmac-signing)).
* **Timeout**: 10 seconds. Non-2xx responses and timeouts are recorded as `notification_failed` events and are **not retried** — design your receiver to be idempotent.

## Body

```json theme={"system"}
{
  "event": "deployment.healthy",
  "ts": "2026-05-19T17:22:03Z",
  "organization": {
    "slug": "acme",
    "name": "Acme Inc"
  },
  "repository": {
    "id": "5b1f-…-c2e9",
    "full_name": "acme/orders-api"
  },
  "deployment": {
    "id": "8e4c-…-a3d1",
    "url": "https://app.slipway.sh/deployments/8e4c-…-a3d1",
    "commit_sha": "9a1f6c…",
    "branch": "feat/checkout",
    "status": "healthy",
    "trigger": "pull_request",
    "pr_number": 142,
    "public_urls": {
      "api": "https://orders-api-3f9a2c1b.preview.acme.dev",
      "web": "https://orders-web-3f9a2c1b.preview.acme.dev"
    },
    "expires_at": "2026-05-19T22:22:03Z"
  }
}
```

### Field reference

| Field                       | Type    | Notes                                                                                                                                                                                 |
| --------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event`                     | string  | One of `deployment.healthy`, `deployment.updated`, `deployment.failed`, `deployment.torn_down`.                                                                                       |
| `ts`                        | RFC3339 | Time the dispatcher built the payload.                                                                                                                                                |
| `organization.slug`         | string  | URL-safe org slug.                                                                                                                                                                    |
| `organization.name`         | string  | Human-readable org name.                                                                                                                                                              |
| `repository.id`             | UUID    | Stable internal id.                                                                                                                                                                   |
| `repository.full_name`      | string  | `owner/repo` from GitHub.                                                                                                                                                             |
| `deployment.id`             | UUID    | Stable internal id.                                                                                                                                                                   |
| `deployment.url`            | string  | Link back to the deployment detail page. Omitted if no public base URL is available.                                                                                                  |
| `deployment.commit_sha`     | string  | Full 40-char SHA.                                                                                                                                                                     |
| `deployment.branch`         | string  |                                                                                                                                                                                       |
| `deployment.status`         | string  | Snapshot of the row's status at send time. Usually matches the event (`healthy` for `deployment.healthy`, `failed` for `deployment.failed`, `superseded` for `deployment.torn_down`). |
| `deployment.trigger`        | string  | `push`, `pull_request`, `manual`, or `rollback`.                                                                                                                                      |
| `deployment.pr_number`      | int     | Present only when `trigger == "pull_request"`. Omitted otherwise.                                                                                                                     |
| `deployment.public_urls`    | object  | `{ service_name: url }`. Omitted when the spec defines no public services.                                                                                                            |
| `deployment.expires_at`     | RFC3339 | Set on ephemeral previews when status flipped to `healthy`. Omitted otherwise.                                                                                                        |
| `deployment.failure_reason` | string  | Present only on `deployment.failed`.                                                                                                                                                  |

The `updated` event uses the same shape as `healthy` — there is no extra "previous deployment" reference. If you need that, look up the repo's deployments via the API and find the most recent `superseded` row for the same `pr_number`.

## HMAC signing

When the channel has a signing secret, slipway includes:

```
X-Slipway-Signature: sha256=<hex_digest>
```

The digest is computed exactly as:

```
hmac_sha256(raw_request_body, signing_secret)
```

…over the **raw bytes** of the request body, not a re-serialised version. Verify in constant time before trusting the payload. Example in Go:

```go theme={"system"}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
want := "sha256=" + hex.EncodeToString(mac.Sum(nil))
got := r.Header.Get("X-Slipway-Signature")
if !hmac.Equal([]byte(got), []byte(want)) {
    http.Error(w, "bad signature", http.StatusUnauthorized)
    return
}
```

The signing scheme intentionally mirrors slipway's inbound GitHub webhook verifier, so any code you already have for verifying GitHub webhooks will need only a header-name change.

## Delivery failures

If your endpoint returns a non-2xx status or doesn't respond within 10 seconds, slipway writes a `notification_failed` event to the deployment with `data.channel_id`. Deliveries aren't retried — keep your receiver idempotent and use the deployment timeline to spot delivery problems.
