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

# Webhooks

> Receive real-time platform events on your backend server

## Overview

Webhooks deliver platform events (builds going live, purchases, analytics) to your backend via HTTP POST. Your server must respond within 10 seconds.

## Create a webhook endpoint

Developer Portal → your game → **Webhooks → Add Endpoint**

| Field  | Notes                                                |
| ------ | ---------------------------------------------------- |
| URL    | Your HTTPS endpoint — must be publicly reachable     |
| Secret | Used to sign requests — store securely, never commit |
| Events | Select which events to receive                       |

## Available events

| Event                  | Triggered when                                            |
| ---------------------- | --------------------------------------------------------- |
| `BUILD_RECEIVED`       | Build upload completed                                    |
| `BUILD_LIVE`           | Build reviewed and set live                               |
| `BUILD_REJECTED`       | Build failed review                                       |
| `BUILD_DEPRECATED`     | Build replaced by a newer live version                    |
| `SDK_ANALYTICS_EVENT`  | Player analytics event fired                              |
| `CUSTOM_WEBHOOK_EVENT` | Event your game sent via `SusaPlaySDK.Webhooks.SendEvent` |

Any other event name is silently dropped when you save the subscription — check the saved list
in the portal to confirm what was accepted.

## Verify signatures

Every request carries two headers:

| Header                 | Contents                                                                 |
| ---------------------- | ------------------------------------------------------------------------ |
| `X-Platform-Signature` | HMAC-SHA256 of the raw body, hex-encoded, keyed with your webhook secret |
| `X-Platform-Event`     | The event name, so you can route without parsing first                   |

**Always verify the signature before processing.**

```javascript theme={null}
import crypto from 'crypto'

function verifySignature(req, secret) {
  const signature = req.headers['x-platform-signature']
  const expected = crypto
    .createHmac('sha256', secret)
    .update(req.body) // raw body string, not parsed JSON
    .digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  )
}

app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
  if (!verifySignature(req, process.env.WEBHOOK_SECRET)) {
    return res.status(401).end()
  }
  res.sendStatus(200)            // respond fast
  processAsync(req.body.toString()) // heavy work after
})
```

<Warning>
  Parse the raw body for signature verification — never verify against a pre-parsed JSON object.
</Warning>

## Reliability rules

* **Return 200 within 5 seconds.** That is the delivery timeout — anything slower is recorded as
  a failure.
* **There are no retries.** A delivery that times out or returns an error is logged and dropped.
  Treat webhooks as best-effort notifications, not a guaranteed queue. If a piece of state must
  be correct, reconcile it against the API rather than relying on having received an event.
* **Be idempotent anyway.** Respond fast, queue the work, and make replays harmless.
* **Cap your endpoints.** A game can have at most 20 webhooks.

## Secrets

The signing secret is shown **once**, when you create the webhook. It cannot be read back
afterwards — the portal only shows its last four characters. Store it in your own secret manager
at creation time.

If you lose it, or if you want to rotate on a schedule, use **rotate** in the portal. That issues
a new secret and shows it once. Deliveries signed with the old secret stop verifying immediately,
so update your endpoint in the same window.

## Test a webhook

Developer Portal → Webhooks → select endpoint → **Send Test Event**. Inspect the delivery log for status code, response time, and response body.
