> ## Documentation Index
> Fetch the complete documentation index at: https://nango-tiktok-accounts-update.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Get real-time updates when new data is available.

## Webhooks from Nango to your app[](#from-nango)

You can configure Nango to send a webhook to your app every time a sync finishes and new data is available.

To set this up, go to [Project Settings page](https://app.nango.dev/project-settings) and set your webhook receive URL there.

<Tip>
  You can change the webhook delivery so it sends every time a sync finishes regardless if new data is available in project settings.
</Tip>

The webhook from Nango is a POST request with the following body:

```json
{
    "connectionId": "<user-id>",              // The connection's ID, as set by you in nango.auth
    "providerConfigKey": "<integration-id>",  // The name of the integration in Nango, e.g. github
    "syncName": "<sync-name>",                // The name of the sync as defined in nango.yaml, e.g. github-tickets
    "model": "<data-model>",                  // The name of the data model, e.g. ticket
    "responseResults": { "<DataModel>": { "added": 123, "updated": 123, "deleted": 123 } }, // The number of new/updated/deleted records, per object type.
    "syncType": "INITIAL" | "INCREMENTAL",   // "Initial" or "incremental" run
    "queryTimeStamp": "2023-05-31T11:46:13.390Z", // Use this with "delta" in listRecords to fetch the data of this sync. Note that this property will be null for the initial sync job.
}
```

If your sync returns multiple models, you may receive multiple webhooks for the same sync run (one for each model).

For full type safety, the `@nangohq/node` package exports a type annotation for the webhook. Example usage:

```ts
import express from 'express';
import bodyParser from 'body-parser';
import { NangoSyncWebhookBody } from '@nangohq/node';

const app = express();

// Middleware
app.use(bodyParser.json());

// POST Endpoint
app.post('/webhook', (req, res) => {
    const response: NangoSyncWebhookBody = req.body;
    console.log(response);
    res.status(200).send('Received POST request');
});
```

<Tip>
  Webhooks with non-2xx responses are retried with exponential backoff.
</Tip>

## Webhook Verification

You can validate that the webhook indeed comes from Nango by looking at the
`X-Nango-Signature` header which is a SHA-256 hash built using the secret
key found in your project settings combined with the payload of the request body:

```ts
import crypto from 'crypto';

const secretKeyDev = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
const signature = `${secretKeyDev}${JSON.stringify(payload)}`;
const hash = crypto.createHash('sha256').update(signature).digest('hex');
```

If the value of the `X-Nango-Signature` matches that of `hash` (as seen above)
then the request passed validation.

## Webhooks from external APIs to Nango[](#to-nango)

You can handle incoming webhooks from external APIs using Nango:

* Configure the webhook with your application as you would normally do
* Write a *sync* script that returns the data models you want (it can perform additional API requests if needed)
* Upon webhook reception, trigger the *sync* script and pass it the webhook payload- Upon webhook reception, trigger the *sync* script and pass it the webhook payload
