# Nango Webhooks

## When to Use This Skill

* How do I receive Nango webhooks in my app?
* How do I verify the `X-Nango-Hmac-Sha256` webhook signature?
* Why does Nango webhook signature verification fail? (wrong key, parsed body, legacy header)
* How do I save the connection ID from an `auth` / `creation` webhook?
* How do I react to a `sync` webhook and fetch the changed records?
* How do I handle `forward` webhooks (HubSpot, Slack, GitHub, etc. events forwarded by Nango)?

## Verification (core)

Nango signs the **raw request body** with HMAC-SHA256, keyed with the environment's **webhook signing key** (Environment Settings > Webhooks > Signing key) used as a plain UTF-8 string, and sends the lowercase hex digest in `X-Nango-Hmac-Sha256`. There is no timestamp or prefix. Ignore the legacy `X-Nango-Signature` header (plain SHA-256, deprecated).

Node (the [`@nangohq/node`](https://www.npmjs.com/package/@nangohq/node) SDK does the same thing):

```javascript
const { Nango } = require('@nangohq/node');

const nango = new Nango({
  apiKey: process.env.NANGO_API_KEY,                        // API calls
  webhookSigningKey: process.env.NANGO_WEBHOOK_SIGNING_KEY, // webhook verification
});
// rawBody must be the unparsed body as a string
const isValid = nango.verifyIncomingWebhookRequest(rawBody, req.headers);

```

Python (no SDK, manual):

```python
import hmac, hashlib

def verify(raw_body: bytes, signature: str, signing_key: str) -> bool:
    expected = hmac.new(signing_key.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, (signature or "").lower())

```

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/nango-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/nango-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/nango-webhooks/examples/fastapi/).

## Webhook Types

Nango has no per-event names; route on the body's `type` (and `operation` / `success` for auth, `success` for sync). Ignore unknown types: Nango adds new ones without treating it as a breaking change.

| `type` | Key fields | When it fires |
| --- | --- | --- |
| `auth` | `operation`: `creation` | `override` | `refresh` | `deletion`; `success`; `connectionId`; `providerConfigKey`; `tags` | Connection created, re-authorized, token refresh failed or recovered, connection deleted |
| `sync` | `success`; `syncName`; `model`; `modifiedAfter`; `responseResults`; `checkpoints`; `error` | A sync function run finished (succeeded or failed) |
| `forward` | `from`; `providerConfigKey`; `connectionId` (optional); `payload`; `unverified` (optional) | An external API webhook was forwarded through Nango |
| `async_action` | `connectionId`; `providerConfigKey`; `payload` | An async action finished |

`auth` + `creation` with `success: true` is the one you **must** handle: it is how you learn the new `connectionId` (match it to your user via `tags`).

> **For payload details**, see [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/nango-webhooks/references/overview.md) and [Nango's webhook docs](https://nango.dev/docs/guides/platform/webhooks-from-nango).

## Important Headers

| Header | Description |
| --- | --- |
| `X-Nango-Hmac-Sha256` | Hex HMAC-SHA256 of the raw body (use this) |
| `X-Nango-Signature` | Legacy plain SHA-256 signature (do not use) |
| `X-Nango-Webhook-Unverified` | `true` on forwards where Nango could not check the external provider's signature |

## Environment Variables

```bash
NANGO_WEBHOOK_SIGNING_KEY=your_webhook_signing_key   # Environment Settings > Webhooks > Signing key
NANGO_API_KEY=your_nango_api_key                     # Environment Settings > API key (SDK constructor + API calls)

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 nango --path /webhooks/nango

```

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/nango-webhooks/references/overview.md) - Webhook types and payloads
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/nango-webhooks/references/setup.md) - Webhook URLs, signing key, per-connection overrides
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/nango-webhooks/references/verification.md) - Signature verification details, key rotation, gotchas