Webhooks

Use webhooks to be notified about events that happen in a Follow Up Boss account.

🚧

Owner Permissions Required

Only the owner has access to creating, updating, or deleting webhooks.

Overview

Webhooks post JSON to a specific URL every time an event listed below is triggered. Webhooks remove the need to poll for changes. When an event occurs--for example a person is assigned to a different agent, this event will be sent to your system as an HTTP POST to the webhook URL configured for the peopleUpdated event.

Examples of what you might use webhooks for:

  • Update a person's name in your database when it is changed in Follow Up Boss
  • Update a person's email or phone in your database when it is changed in Follow Up Boss
  • Re-assign a person in your system when it is re-assigned in Follow Up Boss
  • When a Zillow lead is added to Follow Up Boss you add it to your IDX search website

📘

Batch Updates

The following actions can result in a large number of people updates:

  • Tags added or removed
  • Stage updated
  • Source updated
  • Agent re-assigned
  • Lender re-assigned

If one of these actions result in a large number of people being updated, the webhook event notification may be split into multiple requests.

Supported webhook events

People

peopleCreated, peopleUpdated, peopleDeleted, peopleTagsCreated, peopleStageUpdated,peopleRelationshipCreated,peopleRelationshipUpdated,peopleRelationshipDeleted

peopleUpdated

One or more of the following fields are updated in a person:

  • Name name firstName lastName
  • Emails emails
  • Phone Numbers phones
  • Address addresses
  • Price price
  • Background background
  • Assigned Agent assignedTo assignedUserId
  • Assigned Lender assignedLenderName assignedLenderId
  • Contacted contacted
  • Stage stage stageId
  • Lead Source source sourceUrl
  • Tags tags
  • Custom Fields
  • Relationship is created, updated, or deleted

📘

Custom Fields

If you want to view custom field data following a peopleUpdated event, make sure you add the query parameter fields=allFields to your GET /people request, custom fields are not returned by default.

peopleDeleted

When a person is deleted all associated data is deleted as well e.g. notes, calls, text messages, etc. There will not be any delete events triggered for these resources when this happens.

JSON sample of event notification:

{
    "eventId": "64d0ad74-3aab-4b30-89c9-7337398cf8b4",
    "eventCreated": "2016-12-12T15:19:21+00:00",
    "event": "peopleDeleted",
    "resourceIds": [1234,5322,29456],
    "uri": null
}

peopleTagsCreated

When a tag is added to a person, the payload will include the name of the new tag. Multiple tags and person ids may be included. Note: The webhook will fire regardless of whether a tag was previously removed and re-added to a contact.

JSON sample of event notification:

{
    "eventId": "e8d9f150-5dac-4c53-8c0f-06560dc4ec08",
    "eventCreated": "2019-07-01T17:22:28+00:00",
    "event": "peopleTagsCreated",
    "resourceIds": [
        40773,
        40772
    ],
    "uri": "https://api.followupboss.com/v1/people?id=40773,40772",
    "data": {
        "tags": [
            "Kingsbury"
        ]
    }
}

peopleStageUpdated

When a person's stage is updated, the payload will include the name of the new stage.

JSON sample of event notification:

{
    "eventId": "e0ac086a-879a-4d8b-869a-fe53151e34f4",
    "eventCreated": "2019-07-01T17:12:32+00:00",
    "event": "peopleStageUpdated",
    "resourceIds": [
        40942
    ],
    "uri": "https://api.followupboss.com/v1/people?id=40942",
    "data": {
        "stage": "Free Trial"
    }
}

Notes

notesCreated, notesUpdated, notesDeleted

Reactions (Beta)

reactionCreated,reactionDeleted

{
    "eventId": "e0ac086a-879a-4d8b-869a-fe53151e34f4",
    "eventCreated": "2019-07-01T17:12:32+00:00",
    "event": "reactionCreated",
    "resourceIds": [9387],
    "uri": "https://api.followupboss.com/v1/reactions/9387",
    "data": {
        "refType": "Note",
        "refId": 3827,
        "refUri": "https://api.followupboss.com/v1/notes/3827?includeReactions=true"
    }
}

Threaded Replies (Beta)

threadedReplyCreated, threadedReplyUpdated, threadedReplyDeleted

{
    "eventId": "e0ac086a-879a-4d8b-869a-fe53151e34f4",
    "eventCreated": "2019-07-01T17:12:32+00:00",
    "event": "threadedReplyCreated",
    "resourceIds": [9387],
    "uri": "https://api.followupboss.com/v1/threadedReplies/9387",
    "data": {
        "refType": "Note",
        "refId": 3827,
        "refUri": "https://api.followupboss.com/v1/notes/3827?includeThreadedReplies=true"
    }
}

Emails

emailsCreated, emailsUpdated, emailsDeleted

Tasks

tasksCreated, tasksUpdated, tasksDeleted

Appointments

appointmentsCreated, appointmentsUpdated, appointmentsDeleted
These webhooks only fires when the appointment was created in Follow Up Boss, not when we sync appointments created on Integrated Calendars (i.e. Google or Office 365 calendars).

Text Messages

textMessagesCreated, textMessagesUpdated, textMessagesDeleted

Calls

callsCreated, callsUpdated, callsDeleted

Email Marketing Events

emEventsOpened
People open an email marketing email.

emEventsClicked
People click a link in an email marketing email.

emEventsUnsubscribed
People unsubscribe from email marketing emails.

Deals

dealsCreated, dealsUpdated, dealsDeleted

📘

dealsUpdated Event

This event does not fire for files being changed on the deal.

People Events

eventsCreated
People perform an action on your IDX website, e.g. view a property.

Registering a webhook

Send an HTTPS POST to the /v1/webhooks endpoint with a JSON object that specifies the event and callback URL.

🚧

Limited number of webhooks per event

There is a limit of two web hooks per event per system which can be registered.

Unused webhooks should be unregistered to prevent hitting the limit. In order to unregister a webhook, first call the GET /v1/webhooks API with the account owner API key and the X-System header that you are using for the webhook subscriptions to retrieve the list of webhooks that are registered along with the IDs. From there, make a call to the DELETE /v1/webhooks/:id API and unregister any unused webhooks.

If multiple endpoints for an event are desired, a single webhook should be registered which in turn handles the fan out to multiple endpoints internally to your system. Keep in mind the best practices below about de-coupling the message receiving and workload so that the initial call does not timeout.

🚧

Webhook Security

When registering a webhook, you should use a unique identifier that maps a user to your system. Do not use API keys as part of a URL request.

❗️

HTTPS Only

Callback URLs must be a secure endpoint.

❗️

X-System Header is Required

The X-System HTTP Header is required for all requests to /v1/webhooks endpoints.

POST /v1/webhooks HTTP/1.1
Content-Type: application/json
X-System: AcmeLeadProvider
...
{
  "event": "peopleCreated",
  "url": "https://acmeLeadProvider.com/callbacks/fub/peopleCreated"
}

The response will be JSON encoded representation of the webhook created.

{
  "id": 1244,
  "status": "Active",
  "event": "peopleCreated",
  "url": "https://acmeLeadProvider.com/callbacks/fub/peopleCreated"
}

Receiving webhook events

Create an endpoint that accepts HTTP POST requests at the URL specified in the registered webhook. The body of the request will be JSON encoded. To acknowledge the receipt, your endpoint should respond within 10 seconds with a 2XX HTTP status code such as 200 or 204. Any other response will indicate that you did not receive the webhook and we will continue to retry at various intervals for up to 8 hours.

For example, the endpoint at https://acmeleadprovider.com/callbacks/fub/peoplecreated would receive the following HTTP POST when a person is created in Follow Up Boss:

POST /callbacks/fub/peoplecreated HTTP/1.1
Content-Type: application/json
...
{
  "eventId": "152d60c0-79da-4018-a9af-28aec8a71c94",
  "eventCreated": "2016-12-12T15:19:21+00:00",
  "event": "peopleCreated",
  "resourceIds": [1234,3244,3232],
  "uri": "https://api.followupboss.com/v1/people?id=1234,3244,3232"
}

Verify the request

With each request, we pass along a FUB-Signature header. You can use this string value to verify the request is from us using your X-System-Key provided when you registered your system.

You will want to base64 encode the JSON payload you received from the request (non-prettified), then produce a SHA256 hash with this base64 encode value and your X-System-Key , this value should match the FUB-Signature value.

function isFromFollowUpBoss(string $context, string $signature): boolean {
    $calculated = hash_hmac('sha256', base64_encode($context), YOUR_X-SYSTEM-KEY);

    return $signature === $calculated;
}

if (isFromFollowUpBoss($jsonPayload, $signatureFromHeader)) {
    // do something
}

Handling webhook events

The endpoint that handles events should do an HTTP GET to the resource URI specified in the event. Then compare the response to the local database and apply changes that are found.

See the code samples below for handling webhook events:

<?php
const FUB_API_KEY = 'API Key for an Admin user in the Follow Up Boss Account';

// Retrieve the request's body and parse it as JSON
$input = @file_get_contents("php://input");
$event_json = json_decode($input);

$event = $event_json->{'event'};
$resource_uri = $event_json->{'uri'};

// for peopleCreated and peopleUpdated events fetch the people
// at the resource URI

$curl = curl_init($resource_uri);

$headers = array(
    'Authorization: Basic '. base64_encode(FUB_API_KEY . ":")
);

curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($curl);
curl_close($curl);

$remote_records = json_decode($result);

// Compare the remote record with your local record

http_response_code(200); // PHP 5.4 or greater

echo('OK');

Requesting webhook events

Individual webhook events can be requested from /v1/webhookEvents/:id. This can useful if your system was unavailable to receive events for some reason and there are events older than 3 days that were missed.

🚧

Webhook Event Retries

If your system is unavailable or responds with an HTTP status code other than 2XX such as 200 or 204, FUB will continue to retry for up to 8 hours.

Disabling webhooks

In order to disable a webhook manually, you need to call the DELETE event for /v1/webhooks/ with the corresponding ID for your registered webhook.

👍

Automatic Webhook Disabling

It is recommended that you set up your webhooks to return an HTTP code of 406 or 410 when you want them deleted automatically (such as when a customer is no longer utilizing your system).

Webhook best practices

Setup your system to de-couple receiving webhook events from fetching the resource specified in the event. For example--the web service that receives events could record the event in a local database table. A separate backend process could be created to monitor this table for new rows and fetch the resource specified in the event. By separating these, the web service that handles receiving webhooks is doing less and is, therefore less likely to fail. The process that processes the events can contain all the complex logic to fetch the resource from Follow Up Boss, reconcile with your local system and mark the event as processed in the table. If this process fails or breaks it can be debugged independently of the web service. The table that stores events is the source of truth as to what webhook events have been received and processed.

Debugging webhooks

Since webhooks require a publicly accessible URL to function they can be hard to test from your local machine. It is recommended that you use a service like Request Bin when you are developing your webhook endpoints.

Common webhook mistakes

  • Make sure you provide the correct URL when registering a webhook. You can list all your webhooks at the /v1/webhooks endpoint.
  • Make sure the webhook endpoint is returning a 2XX HTTP status code such as 200
  • When registering a webhook make sure you are setting the X-System header. You can also include the system param in the query string or post data. For example: https://api.followupboss.com/v1/webhooks/32?system=AcmeCo
  • If you are setting up webhooks for multiple Follow Up Boss accounts be sure to include a Follow Up Boss account identifier in the registered webhook URLs. Your webhook URLs should look like this: https://acmeLeadProvider.com/callbacks/fub/account12/peopleCreated or https://acmeLeadProvider.com/callbacks/fub/peopleCreated?fub_account=12