# Webhooks

{% hint style="warning" %}
We updated our API endpoints and updated authentication requirements. This update introduces new functionalities, updated naming, route paths, parameters, and body.<br>

**Previous Names:**\
\&#xNAN;*Example 1: Members* have been renamed to *Locations.*\
*Example 2: The identifier `faundit_memberID` is `locationID` now.*

**Removed Requirements:**&#x20;

*Example 3: The`faundit_memberID` is no longer required on the headers. Instead, it would be expected in some endpoints as part of the body, under the property name `locationID.`*<br>

If you integrated with our API before this update, everything will continue to function as expected. You can also use your old `faundit_memberID` as the new `locationID`.

Please contact us if you encounter any unexpected issues.
{% endhint %}

### Security

For security purposes, every webhook is delivered with signature headers for verification. You can get your webhook signing key by contacting <tech@faundit.com>.

#### **Signature Headers**

We send two signature headers:

| **Header**                 | **Hash Input**          | **Status**             |
| -------------------------- | ----------------------- | ---------------------- |
| `X-Faundit-Signature-Next` | `v1:<timestamp>:<body>` | ✅ Recommended          |
| `X-Faundit-Signature`      | `v0:<timestamp>`        | ⚠️ Legacy (deprecated) |

{% hint style="info" %}
New integrations should use X-Faundit-Signature-Next as it includes payload integrity verification.
{% endhint %}

**Verifying the Signature (Recommended - Next /** **V1)**

1. Retrieve the `X-Faundit-Timestamp` header from the request
2. Get the raw request body as a string (do not parse it first)
3. Concatenate: `v1:<timestamp>:<body>`
4. Compute HMAC-SHA256 using your webhook signing secret
5. Compare the result (hex-encoded) with the `X-Faundit-Signature-Next` header

**Example (Node.js):**&#x20;

```js
const crypto = require('crypto');
function verifyWebhookSignature(req, signingSecret) { 
    const timestamp = req.headers['x-faundit-timestamp']; 
    const signature = req.headers['x-faundit-signature-Next']; 
    const rawBody = req.body; // Must be raw string, not parsed JSON
    
    const expectedSignature = crypto 
        .createHmac('sha256', signingSecret) 
        .update(v1:${timestamp}:${rawBody}) 
        .digest('hex');
    
    return signature === expectedSignature; 
} 
```

**Legacy Verification (V0) - Deprecated**

The legacy `X-Faundit-Signature` header is computed from `v0:<timestamp>` only (without the body). This method is deprecated and will be removed in a future update.

```js
// Legacy - do not use for new integrations
const expectedSignature = crypto
  .createHmac('sha256', signingSecret)
  .update(`v0:${timestamp}`)
  .digest('hex');
```

### Supported Events

| Event          | Description                                                                   |
| -------------- | ----------------------------------------------------------------------------- |
| item-status    | Event triggered when an item changes its status or there is a new item.       |
| request-status | Event triggered when an request changes its status or there is a new request. |

### **Webhook event payload**

#### Item event

This event will contain the *ID* of the item, *locationID* that you have to store to identify to what property the data belongs, the current *status* of the item, and the *timestamp* of when this event was performed.

An item can have different statuses, they are:<br>

<table><thead><tr><th width="374">Status</th><th>Status Code</th></tr></thead><tbody><tr><td>Contact Missing</td><td>contact-missing</td></tr><tr><td>Waiting for Response</td><td>waiting-response</td></tr><tr><td>Wrong Owner</td><td>wrong-owner</td></tr><tr><td>Pickup by Guest</td><td>pickup-by-guest</td></tr><tr><td>Left Behind</td><td>left-behind</td></tr><tr><td>Finished</td><td>finished</td></tr><tr><td>Shipment Paid</td><td>shipment-paid</td></tr><tr><td>Pickup Scheduled</td><td>pickup-scheduled</td></tr><tr><td>In Route</td><td>in-route</td></tr><tr><td>Delivered</td><td>delivered</td></tr><tr><td>Deleted</td><td>deleted</td></tr><tr><td>Expired</td><td>expired</td></tr><tr><td>Anonymized</td><td>anonymized</td></tr></tbody></table>

An example of the payload of this event can be:

```json
{
       "event-type": "item-status",
       "data": { 
              "id": 133378,
              "timestamp": "2022-08-01T08:48:09.621Z",
              "status": "shipment-paid",
              "locationID": "locationID"
        }
}
```

#### Request event

This event will contain the *id* of the request, *locationID* that you have to store to identify to what property the data belongs, the current *status* of the request, and the *timestamp* of when this event was performed.

A request can have different statuses, they are:

| Status     | Status Code |
| ---------- | ----------- |
| Registered | registered  |
| Not Found  | not-found   |
| Resolved   | resolved    |
| Deleted    | deleted     |
| Expired    | expired     |
| Anonymized | anonymized  |

```json
{
       "event-type": "request-status",
       "data": { 
              "id": 201313,
              "timestamp": "2022-11-22T18:13:09.621Z",
              "status": "registered",
              "locationID": "locationID"
        }
}
```
