Learn how to configure and optimize webhooks for your integration.

## [Determine what events to subscribe to](https://docs.moov.io/guides/webhooks/set-up-webhooks/#determine-what-events-to-subscribe-to)

To minimize unnecessary burden on your server, only subscribe to events you need. See our [webhook events](https://docs.moov.io/guides/webhooks/webhook-events/) guide for a full list of events and payload examples.

## [Create a webhook endpoint on your server](https://docs.moov.io/guides/webhooks/set-up-webhooks/#create-a-webhook-endpoint-on-your-server)

Set up an HTTPS endpoint that accepts and processes HTTP `POST` calls. A URL with HTTPS is required.

## [Register your endpoint in the Moov Dashboard](https://docs.moov.io/guides/webhooks/set-up-webhooks/#register-your-endpoint-in-the-moov-dashboard)

In the Moov Dashboard, navigate to **Developers** and select **Webhooks**. There, you can include your endpoint URL, an optional description, and which events you’d like to subscribe to.

## [Test the endpoint](https://docs.moov.io/guides/webhooks/set-up-webhooks/#test-the-endpoint)

In the Moov Dashboard, you can trigger a test event to your webhook by selecting the **Send test webhook** action.

The target server URL will receive a test payload that looks like this:

```json
{
  "eventID": "d9d18a42-d1ea-4e4c-b671-0fa93e24d584",
  "type": "event.test",
  "data": {
    "ping": true
  },
  "createdOn": "2024-01-26T20:42:25Z"
}
```

## [Verify events were sent by Moov](https://docs.moov.io/guides/webhooks/set-up-webhooks/#verify-events-were-sent-by-moov)

Check out our example [webhook handler project](https://github.com/moovfinancial/webhook-handler) on GitHub.

Every event Moov sends to a webhook endpoint includes a signature which allows you to verify that Moov (and not a third party) sent these events to your service.

Use the following steps to construct your hash and compare it against the event signature:

1. Get the signing secret from the [Moov Dashboard](https://dashboard.moov.io/developers/webhooks).
2. Get the following header values from the received `POST`:
   - `X-Timestamp`
   - `X-Nonce`
   - `X-Webhook-ID`
   - `X-Signature`
3. Prepare the string: `{X-Timestamp} + "|" + {X-Nonce} + "|" + {X-Webhook-ID}`.
4. Calculate the expected signature using the hashing algorithm HMAC-SHA512 with the signing secret and string from step 3.
5. Check the expected signature matches the value set in `X-Signature`.

If the hash you created matches the value of the `X-Signature` header, you know that the event came from Moov. Otherwise, your service should discard the event.

See the example below:

```jsx
const hmacSHA512 = require("crypto-js/hmac-sha512");

// Get your signing secret from dashboard.moov.io
const webhookSecret = process.env.WEBHOOK_SECRET;

// Check if the hash of headers match the signature
const isSigned = (timestamp, nonce, webhookId, signature) => {
  const concatHeaders = `${timestamp}|${nonce}|${webhookId}`;
  const checkHash = hmacSHA512(concatHeaders, webhookSecret);

return signature === checkHash.toString();
}

// Serverless function
exports.handler = async (event, context, callback) => {
  if (!event.body) {
    console.log("Invalid request");
    callback(null, {
      statusCode: 400,
      body: "Invalid request"
    });
  }

if (!isSigned(
    event.headers["X-Timestamp"],
    event.headers["X-Nonce"],
    event.headers["X-Webhook-ID"],
    event.headers["X-Signature"])
  ) {
    console.log("Signature is invalid");
    callback(null, {
      statusCode: 400,
      body: "Signature is invalid"
    });
  }

let webhook;
  try {
    webhook = JSON.parse(event.body);
  } catch (err) {
    console.log("Invalid JSON");
    callback(null, {
      statusCode: 400,
      body: "Invalid JSON"
    });
  }

// Logs the event message payload

console.log(event.body);

callback(null, {
    statusCode: 200
  });
};
```

## [Best practices](https://docs.moov.io/guides/webhooks/set-up-webhooks/#best-practices)

We recommend implementing the following best practices when using webhooks with Moov.

### [Subscribe to a minimum number of events](https://docs.moov.io/guides/webhooks/set-up-webhooks/#subscribe-to-a-minimum-number-of-events)

To optimize performance and avoid overloading your server, subscribe to a minimum number of events. Alternatively, you can set up multiple webhooks subscribed to specific event types.

### [Respond within 5 seconds](https://docs.moov.io/guides/webhooks/set-up-webhooks/#respond-within-5-seconds)

If Moov does not receive a `2xx` response from your server within 5 seconds, we’ll consider the delivery of the webhook event as failed. Moov will retry the webhook multiple times, for up to 24 hours. If webhook servers return a `404` after the last retry, the webhook will become disabled.
