Webhooks

You can set up FindFace Multi to automatically send notifications about specific events, episodes, and counter records to a given URL. To do so, create and configure a webhook. In this case, when such an event, episode, or counter record occurs, FindFace Multi will send an HTTP request to the URL configured for the webhook.

You can use webhooks for various purposes, for instance, to notify a user about a specific event, invoke required behavior on a target website, and solve security tasks such as automated access control.

In this section:

Configure Webhook

Important

You need Administrator privileges to create a webhook.

Note

To use the webhooks, make sure that at least one of the following parameters is specified in /etc/findface-security/config.py: SERVICE_EXTERNAL_ADDRESS or EXTERNAL_ADDRESS.

To create and configure a webhook, do the following:

  1. Navigate to the Preferences tab. Click Webhooks.

  2. Click +.

    create_webhook_en

  3. Specify the webhook title.

    webhook_en

  4. Specify URL to automatically send notifications to.

  5. You can send notifications in batches. Specify the maximum number of notifications in a webhook batch. The actual number may be less.

  6. Specify the maximum number of attempts to send a notification. The interval between attempts increases exponentially with a maximum of 100 seconds.

    Important

    To receive all messages since the connection loss, should it happen, set 0. Set 1 to omit old messages.

  7. FindFace Multi will be automatically sending notifications on events, episodes, and counters which match given filters. The following filters are available:

    Recognition events (face, body, car):

    • allowed_bs_types: object tracking mode, possible values: overall, realtime.

    • camera_group_in: camera group id, number.

    • camera_in: camera id, number.

    • matched_lists_in: watch list id, number.

    • matched_dossier_in: matched dossier id, number.

    • matched: event matched status (true or false), boolean.

    • confidence_gte: minimum confidence, number.

    Episodes:

    • allowed_types: episode status, possible values: an episode opening (episode_open), adding a new event into an episode (episode_event), an episode closing (episode_close).

    • camera_group_in: camera group id, number.

    • camera_in: camera id, number.

    • matched_lists_in: watch list id, number.

    • matched: event matched status (true or false), boolean.

    • events_count_gte: minimum number of events in an episode, number.

    • events_count_lte: maximum number of events in an episode, number.

    Counters:

    • counter_in: counter id, number

    • camera_group_in: camera group id, number.

    • camera_in: camera id, number

    • faces_gte: minimum number of faces in a counter record, number.

    • faces_lte: maximum number of faces in a counter record, number.

    • silhouettes_gte: minimum number of silhouettes in a counter record, number.

    • silhouettes_lte: maximum number of silhouettes in a counter record, number.

    {
          "face_events": {
                "allowed_bs_types": [
                      "overall",
                      "realtime"
                ],
                "camera_group_in": [],
                "camera_in": [],
                "matched_lists_in": [],
                "matched_dossier_in": [],
                "matched": true,
                "confidence_gte": 0.75
          },
          "body_events": {
                "allowed_bs_types": [
                      "overall",
                      "realtime"
                ],
                "camera_group_in": [],
                "camera_in": [],
                "matched_lists_in": [],
                "matched_dossier_in": [],
                "matched": true,
                "confidence_gte": 0.75
          },
          "car_events": {
                "allowed_bs_types": [
                      "overall",
                      "realtime"
                ],
                "camera_group_in": [],
                "camera_in": [],
                "matched_lists_in": [],
                "matched_dossier_in": [],
                "matched": true,
                "confidence_gte": 0.75
          },
          "episodes": {
                "allowed_types": [
                      "episode_open",
                      "episode_event",
                      "episode_close"
                ],
                "camera_group_in": [],
                "camera_in": [],
                "matched_lists_in": [],
                "matched": true,
                "events_count_gte": 0,
                "events_count_lte": 999
          },
          "counters": {
                "counter_in": [],
                "camera_group_in": [],
                "camera_in": [],
                "faces_gte": 1,
                "faces_lte": 100,
                "silhouettes_gte": 1,
                "silhouettes_lte": 100
          }
    }
    

    Important

    Use only filters which match your search needs. To turn off a filter, remove it from a webhook. Do not leave a filter empty ([]) as in this case the result of filtration will be empty as well.

    Note

    To get all notifications, pass only curly braces without any enclosed filters:

    {}
    

    Tip

    Example #1. Get notifications about all events:

    { "events": {} }
    

    Example #2. Get notifications of the opening of matched episodes:

    { "episodes": { "allowed_types": ["episode_open"], "matched": true }}
    

    Note

    You can specify several values for filters with square braces. In this case, the webhook will be triggered once one of the values from this filter has been matched. In the example below, you will get an event from the camera group 1 or 3 if a matched dossier is 12 or 25.

    {
            "events": {
                    "camera_group_in": [1, 3],
                    "matched_dossier_in": [12, 25],
            },
    }
    
  8. Check Active.

  9. Click Save.

Webhook in Action

Try out a webhook by capturing event notifications with a simple web server in Python:

from pprint import pprint
from aiohttp import web


async def handle(request):
    pprint(await request.json())
    return web.Response(status=200)


app = web.Application()
# for aiohttp v 3.x
# app.add_routes([web.post('/', handle)])

# for aiohttp v 2.x
app.router.add_post('/', handle)

web.run_app(app, port=8888)

Important

A webhook catcher that you use must return an HTTP 200 response after receiving the webhook request from FindFace Multi, like in the example above.

If no filters are configured for a webhook, this web server will be getting notifications about all events, episodes, and counter records that occur in the system. The notifications have the following format:

To view a webhook pulling status, execute:

sudo journalctl -u findface-security.service | grep 'Webhook'

Success:

May 30 14:13:43 ffsecurity[12441]: INFO    [Webhook(id=6) worker(type=face_events] <queue:  0> Sent batch(len-1, type-"face_events"): ['4355024961160384430']
May 30 14:13:43 ffsecurity[12441]: INFO    [SC:OQSrsPV9] [Webhooks manager-38bc5] Processing message(type="face_events:event_created"). Consumer reception delta: 0.003450
May 30 14:13:43 ffsecurity[12441]: INFO    [Webhook(id=6) worker(type=face_events] <queue:  0> Sent batch(len-1, type-"face_events"): ['4355024961658847580']
May 30 14:13:44 ffsecurity[12441]: INFO    [SC:JtRz2Vuo] [Webhooks manager-38bc5] Processing message(type="face_events:event_created"). Consumer reception delta: 0.001263
May 30 14:13:44 ffsecurity[12441]: INFO    [Webhook(id=6) worker(type=face_events] <queue:  0> Sent batch(len-1, type-"face_events"): ['4355024962087522421']
May 30 14:13:44 ffsecurity[12441]: INFO    [SC:9AnzRJwU] [Webhooks manager-38bc5] Processing message(type="face_events:event_created"). Consumer reception delta: 0.001691
May 30 14:13:44 ffsecurity[12441]: INFO    [Webhook(id=6) worker(type=face_events] <queue:  0> Sent batch(len-1, type-"face_events"): ['4355024962355957878']

Failure:

May 30 14:18:49 ffsecurity[12441]: INFO    [SC:sp34rVQR] [Webhooks manager-38bc5] Processing message(type="face_events:event_created"). Consumer reception delta: 0.001376
May 30 14:18:49 ffsecurity[12441]: WARNING [Webhook(id=6) worker(type=face_events] <queue:  0> Error sending webhook: Cannot connect to host 127.0.0.1:8888 ssl:None [Connection refused]. Attempt 1 out of 10. Next attempt in 0.270 seconds.
May 30 14:18:50 ffsecurity[12441]: WARNING [Webhook(id=6) worker(type=face_events] <queue:  0> Error sending webhook: Cannot connect to host 127.0.0.1:8888 ssl:None [Connection refused]. Attempt 2 out of 10. Next attempt in 0.729 seconds.
May 30 14:18:50 ffsecurity[12441]: INFO    [SC:zUhLHNxN] [Webhooks manager-38bc5] Processing message(type="face_events:event_created"). Consumer reception delta: 0.001368
May 30 14:18:50 ffsecurity[12441]: INFO    [SC:1Q66tcUS] [Webhooks manager-38bc5] Processing message(type="face_events:event_created"). Consumer reception delta: 0.001386
May 30 14:18:50 ffsecurity[12441]: WARNING [Webhook(id=6) worker(type=face_events] <queue:  2> Error sending webhook: Cannot connect to host 127.0.0.1:8888 ssl:None [Connection refused]. Attempt 3 out of 10. Next attempt in 1.968 seconds.
May 30 14:18:52 ffsecurity[12441]: WARNING [Webhook(id=6) worker(type=face_events] <queue:  2> Error sending webhook: Cannot connect to host 127.0.0.1:8888 ssl:None [Connection refused]. Attempt 4 out of 10. Next attempt in 5.314 seconds.
May 30 14:18:55 ffsecurity[12441]: INFO    [SC:5kl6zGrF] [Webhooks manager-38bc5] Processing message(type="face_events:event_created"). Consumer reception delta: 0.001542
May 30 14:18:58 ffsecurity[12441]: WARNING [Webhook(id=6) worker(type=face_events] <queue:  3> Error sending webhook: Cannot connect to host 127.0.0.1:8888 ssl:None [Connection refused]. Attempt 5 out of 10. Next attempt in 14.349 seconds.

Verbose Webhooks

By default, webhook notifications contain only ids of such entities as dossiers, watch lists, cameras, and camera groups. It is possible to get whole entities in notifications by switching webhooks to the verbose mode.

To do so, open the /etc/findface-security/config.py configuration file and set 'VERBOSE_WEBHOOKS': True:

sudo vi /etc/findface-security/config.py

...
FFSECURITY = {
    ...
    # send serialized dossiers, dossier-lists, camera and camera groups in webhooks
    'VERBOSE_WEBHOOKS': True,
    ...
}
...

In the verbose mode, the format of webhook notifications is the following: