# 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"
        }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://faundit.gitbook.io/faundit-api-v2/webhooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
