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

# Explanation

Palomma sends events when something important happens. You can register a URL and Palomma will make an HTTP POST request to that URL, with all the information related to the event that occurred.

<Info>
  To enable webhooks, contact the Palomma team and provide us with the URL you
  want events to be sent to.
</Info>

## Request Structure

### Headers

<ResponseField name="X-Encoded-Data" type="string">
  Base64 encoding of the request body
</ResponseField>

<ResponseField name="X-Signature" type="string">
  Signature used to verify integrity of `X-Encoded-Data`. Computed using an
  HMAC-SHA-256 of `X-Encoded-Data` with the `integrityKey` assigned to the
  merchant.
</ResponseField>

### Body

<ResponseField name="webhookId" type="string">
  Unique ID for webhook notification. Should only be repeated if the
  notification fails to deliver, in which case more attempts to deliver the
  notification might be made.
</ResponseField>

<ResponseField name="timestamp" type="string">
  ISO string for when the webhook notification was created.
</ResponseField>

<ResponseField name="eventType" type="enum">
  One of the following: `payin-link.update` , `payin-source.update` ,
  `payin-request.update` , `payout-target.update` , `payout-request.update`,
  `payin-settlement.update`
</ResponseField>

<ResponseField name="event" type="object">
  One of the following: [Payin Link](/api-documentation/payinLinks/object) ,
  [Payin Source](/api-documentation/payinSources/object) , [Payin
  Request](/api-documentation/payinRequests/object) , [Payout
  Target](/api-documentation/payoutTargets/object) , [Payout
  Request](/api-documentation/payoutRequests/object), [Payin
  Settlement](/api-documentation/payinSettlements/object)
</ResponseField>

## Authentication

Every webhook Palomma sends is signed to ensure the integrity of the data being sent in the webhook.

<Warning>
  Always verify the signature before trusting the contents of the event.
</Warning>

The recommended flow is the following:

1. Retrieve the request headers `X-Encoded-Data` and `X-Signature`.
2. `X-Signature` is an HMAC with the SHA256 hash function of `X-Encoded-Data`. Compute an HMAC-SHA-256 of `X-Encoded-Data` with the `integrityKey` assigned to you, and compare it to `X-Signature`. If the computed signature and `X-Signature` are not equal, the signature is invalid.
3. `X-Encoded-Data` is a Base64 encoded string. Decode it and parse it into a JSON object. If the signature was correct in step 2, you can trust the data in this JSON.

### Example

Here's an example of the steps described above using Node.js.

```javascript webhookExample.js theme={null}
const crypto = require("crypto");

app.post("/", (req, res) => {
  try {
    // Retrieve information from headers to perform validation.
    const encoded_data = req.headers["x-encoded-data"];
    const signature = req.headers["x-signature"];

    // The integrity key provided by Palomma.
    const integrityKey = process.env.PALOMMA_INTEGRITY_KEY;

    // Create an HMAC for validation purposes.
    const signatureRequest = crypto
      .createHmac("sha256", integrityKey)
      .update(encoded_data)
      .digest("hex");

    // Decode the base64-encoded string.
    const decodedData = Buffer.from(encoded_data, "base64").toString("utf-8");

    // Check if the signature matches
    if (signature === signatureRequest) {
      // Code to execute when a valid webhook is received.
      res.status(200).json({ msg: "Success: Webhook is valid!" });
    } else {
      // Response sent when the webhook is invalid.
      res.status(401).json({ msg: "Error: Webhook is NOT valid!" });
    }
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});
```

## Duplicate Requests

Palomma will try resending webhooks that fail to deliver. In these cases, the same webhookId and timestamp will be sent.

When you successfully process a webhook, we recommend you store the `webhookId`. If you see the same `webhookId` in the future, you can safely ignore it.

<Warning>
  It is important that you do not process the same webhook multiple times.
</Warning>
