> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.repliers.com/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Webhooks Implementation Guide

Webhooks allow developers to subscribe to specific events and receive real-time notifications. This guide will walk you through the process of subscribing to events, managing subscriptions, and understanding the types of events available.

### How to Subscribe to Events

To subscribe to an event, you need to send a POST request to the Repliers webhooks endpoint with the target URL and the event you want to subscribe to. Here's an example:

```bash
curl --request POST \
  --url https://api.repliers.io/webhooks \
  --header 'REPLIERS-API-KEY: {ACCOUNT-API_KEY}' \
  --header 'content-type: application/json' \
  --data '{"target_url":"https://yourdomain.com/unique-path","event":"listing.created"}'
```

Note: The target_url value must be unique.

###### Subscription Verification (Important)

Upon a successful subscription, an empty POST request is immediately sent to the target_url containing an X-Hook-Secret header with a random value. To complete the subscription, the subscriber must return a 200 response to this POST containing the same header key and value.

```bash
curl --request POST \
  --url {target_url} \
  --header 'X-Hook-Secret: {random-value}'
```

###### Authentication

All subsequent requests to the specified target will contain the same value for the x-api-key header. This value may be used to authenticate all subsequent requests.

### Supported Events

Here is a list of currently supported events that developers can subscribe to:

* agent.created
* agent.updated
* agent.deleted
* client.created
* client.updated
* client.deleted
* search.created
* search.updated
* search.deleted
* search.match.created
* search.match.updated
* message.created
* message.updated
* message.deleted
* listing.created
* listing.updated
* listing.deleted

### Example JSON Webhook Payloads For Listing Events

Listing events are a very popular use case. For your reference, we've linked to three real webhook payloads for listing.created, listing.updated and listing.deleted events.

* [listing.created.json](https://repliers.com/wp-content/themes/repliers/assets/json/listing.created.json)
* [listing.updated.json](https://repliers.com/wp-content/themes/repliers/assets/json/listing.updated.json)
* [listing.deleted.json](https://repliers.com/wp-content/themes/repliers/assets/json/listing.deleted.json)

### Example Webhook Request

Here's an example of a webhook request sent to a target_url when a listing is deleted:

```bash
curl --request POST \
  --url {target_url} \
  --header 'X-Hook-Secret: {some-value}' \
  --header 'content-type: application/json' \
  --data '{
    "data": {
        "boardId": 49,
        "mlsNumber": "21000009"
    },
    "hook": {
        "id": 123,
        "event": "listing.deleted",
        "header": "x-api-key",
        "secret": "{some-value}",
        "target_url": "{target_url}"
    }
}'
```

### Working With The Previous Object When Listings Are Updated (listing.updated)

When you've subscribed to the **listing.updated** event, you will receive a webhook request to the **target_url** specified in your subscription whenever a listing's information changes. The webhook payload contains two main components: the **previous** object and the **data** object.

The **previous** object provides the fields that have changed along with their previous values, allowing you to compare them to the new values. Here is an example of what the **previous** object may look like:

```json
... },
    "previous": {
        "status": "A",
        "updatedOn": "2024-09-19T16:00:01.000Z",
        "lastStatus": "New"
    }...
```

In this example:

* The **status** field previously held the value 'A'.
* The **lastStatus** field previously held the value 'New'.
* The **updatedOn** timestamp shows when the listing was last updated before the current change.

This means the listing's **status** and **lastStatus** have now been updated to new values, which are stored in the **data** object of the webhook request. You can access the new values in the **data** object like so:

```json
{
  "data": {
    "status": "U",
    "updatedOn": "2024-09-21T12:30:45.000Z",
    "lastStatus": "Sld"
  }...
}
```

In this case, the new values for **status** and **lastStatus** are 'U' and 'Sld', respectively, reflecting the latest state of the listing.

By using the **previous** object, you can track changes in real time, making it easy to trigger actions based on specific field updates or maintain historical records of a listing’s status transitions.

### Configuring Webhooks with Optional Parameters

When setting up or updating a webhook, you can specify optional **json** **configuration** parameters in the body of the request to tailor the webhook behavior to your needs. Below are examples of how you can configure these parameters to refine which events trigger a webhook and what data is included in the webhook payload.

#### Filtering Webhook Triggers

You can add filters to a webhook to specify which events should trigger notifications based on certain field values. Filters can be applied using either a "contains" logic, which triggers the webhook when the field value includes any of the specified values, or an "exact match" logic, which triggers the webhook when the field value exactly matches one of the specified values.

**Example with "contains" logic:**

```json
{
    "configuration": {
        "filters": [
            {
                "field": "office.brokerageName",
                "logic": "contains",
                "values": [
                    "re/max",
                    "redfin"
                ]
            }
        ]
    }
}
```

This configuration triggers the webhook when the `office.brokerageName` field contains "re/max" or "redfin".

**Example with exact match:**

```json
{
    "configuration": {
        "filters": [
            {
                "field": "office.brokerageName",
                "values": [
                    "re/max",
                    "redfin"
                ]
            }
        ]
    }
}
```

This configuration triggers the webhook when the `office.brokerageName` exactly matches "re/max" or "redfin".

Note: The values in the filters are case insensitive.

#### Including Raw Data in Webhook Payloads

If you prefer to receive raw data in the webhook payload, you can configure your webhook accordingly:

```json
{
    "configuration": {
        "raw": true
    }
}
```

This configuration ensures that the raw data is sent along with the webhook payload, providing you with unprocessed data directly from the event.

These configuration options provide flexibility in how you set up webhooks, allowing you to fine-tune the notifications and data you receive based on your specific needs.

### Summary

By following the steps outlined above, you can easily subscribe to and manage webhook events to receive real-time updates and notifications for various actions within your application.

# What questions does this article answer?

* How do I subscribe to Repliers webhook events (API endpoint, payload, required headers)?  
* How does the subscription verification handshake with `X-Hook-Secret` work?  
* How do I authenticate incoming webhook calls (e.g., via shared key)?    
* How are subsequent webhook calls authenticated (e.g., via x-api-key)?  
* Which entity events are currently supported (agents, clients, searches, messages, listings, favorites, etc.)?  
* How should my application handle retries, idempotency, and security for incoming webhook requests? 