The web is not static anymore. Things happen, and we want to know about them. Sometimes called web callbacks or reverse APIs, Webhooks, is a way for applications to communicate these events that take place. In the context of Flamelink, these changes can be anything from a schema update, a newly created content entry, a deleted navigation, or a host of other events that naturally occur as you manage your content.

You already love Flamelink's data flexibility - the webhooks feature is no exception. You set up the event triggers you are interested in, where and how we should let you know, and we will make sure to let you know.

Webhooks enable you to connect your Flamelink content to any external service available on the internet. Do you want to kick off a new build on your CI server when content changes, you can do it? Do you want to broadcast a Slack notification when a contact form is submitted, you can do it? Do you want to integrate with a complex bespoke API, you can probably do it! If the service can receive an HTTP request, the webhooks feature allows you to integrate with it.

Overview and Best Practices

Flamelink webhooks provide a powerful mechanism for notifying you any time an event happens in your project. There are a few things to be aware of that will help you configure your webhook integration.

Flamelink will send a Webhook request event for each change that is detected in your project (that you selected to "listen" to). Each event has some metadata associated with it that can be used in your integration.

Event Metadata

By default, the payload (request body) that Flamelink sends includes all of the event metadata, but it is recommended to rather read the data from the request headers than from this body request. The reason this is recommended is because if you use a custom payload, you might not have these fields included.

HTTP headers are case-insensitive, so the following headers might have different casing when it reaches your integration endpoint.


The following headers are included for each request:
x-flamelink-event-id :
Each event has a unique event ID that can be used as idempotency key to ensure you do not process the same event more than once.

Flamelink does not guarantee that only one event will be delivered and rather aims for an "at least once" solution.

If it is critical for your integration that you do not process the same event twice, it is advised that you keep track of all event ID's you have received and ignore any duplicates.

x-flamelink-event-type :
An event type consists of a module and an action separated by a period (.), for instance: if the event is for a newly created schema, the event type will be schemas.create 

x-flamelink-project-id :
The ID of your Flamelink project from which the change originated. This can be useful if you use a single URL (endpoint) for multiple projects and you want to handle them differently.

x-flamelink-webhook-id :
The ID of the Webhook configuration. Similar to the Project ID, if you use the same endpoint for different Webhook configuration, you can distinguish between them using this header.

x-flamelink-livemode :
This header will always be "true" for all event requests, except for when a Webhook test is sent from within the app, then it will be "false".

x-flamelink-retry-count :
This header will show the number of retries that Flamelink has sent for the particular event. It will be 0  for the first attempt.

x-flamelink-signature :
If you have the "Sign Request" webhook config setting enabled, Flamelink will set this header with a secure signature that you can use to verify that a request definitely originated from a Flamelink server and that it hasn't been tampered with in between Flamelink and your endpoint.

Read more about verifying request here.

authorization :
If you set basic authentication details in your webhook config, Flamelink will set the authorization  header as per standard basic auth functionality.

Delivery attempts and retries

Flamelink expects a success confirmation from each Webhook request and considers any response with an HTTP response status in the 200 to 209 range a success.
All other responses will be seen as failures and will be re-attempted for a number of times, using exponential back off, before it will permanently be discarded.

Event handling

It is recommended that you use the event ID (x-flamelink-event-id header) to check that you do not process duplicate events. In case of duplicates, it is important to still respond with a success response, even though you can ignore processing it again, otherwise Flamelink will retry the request.

Flamelink currently waits a maximum of 60 seconds for your success response before it times out and considers the response failed, so if processing is not mission-critical it is advised to respond immediately and then process the event.

Order of Events

Flamelink does not guarantee delivery of events in the order in which they are generated. Event ID's are also not generated sequentially, and can therefore not be used to determine the order of events.

Setting up a Webhook

If your project plan supports the Webhooks feature, you should see a link in the project side navigation that will take you to the "Webhooks" section.

The Flamelink webhooks feature works 100% server-side, which means that requests will still be triggered even when the particular change event took place from outside the app. These changes can occur in your app or website, using one of our SDK's, from within the Firebase console or any other updates to your Firebase project. To have the webhook feature work outside the Flamelink app, however, does mean that we need server-side access to your project so that we can "listen" to these changes taking place. To give us server-side access, we require that you upload a Firebase service account for your project.

If you are not familiar with Google Cloud Platform service accounts, you can read more here and here. In short, a service account is a particular type of Google account that is used by applications, instead of users, to access certain parts of your Google/Firebase project.

Since Firebase is part of the Google Cloud Platform services, they have made it easy to generate a service account to access your Firebase services specifically.

To generate a service account now, go to the Project Settings section in the Firebase Console, make sure "Service accounts" is selected and then click the "Generate new private key" button. Save the generated file somewhere on your machine where you can easily find it - you're going to have to upload it next from within Flamelink.


Once you have your service account file, open the Flamelink app and log into your project. Navigate to the "Settings" section. At the top of the "General" section, you should see the "Service Account" panel from which you upload the file. Click the upload button now and select the file you just downloaded from the Firebase console. If the upload was successful, you should receive a success notification telling you so.

Providing a service account is a once-off action, so you would not need to do it again unless you want to replace it with another one.

Now that you have your service account set, you can configure your first webhook. 

From within the Flamelink app, navigate to the "Webhooks" section from the side navigation. You should see an empty table because we have not created your webhook yet. Click "New Webhook".

From the "Webhook Setup" screen, you can now set up your webhook. The most basic webhook configuration requires a name for you to identify it, the event(s) that trigger the request and where (the URL endpoint) Flamelink should send the request.

Configuration Options

Webhook Name: [required]
A descriptive name for the webhook, for you to identify it.
Examples: "Trigger build on CI Server", "Send Slack notification for content update", "Email new contact entries", etc.

Enabled:
Toggle whether the webhook should be enabled or not. Disabled webhooks will not send out any requests.

HTTP Method:
The HTTP method used for the request - defaults to POST.

URL: [required]
A valid URL to which Flamelink should send the webhook requests - the endpoint.

A valid URL is one that is not a Private IP, Localhost, Hostnames without a Top Level Domain or one that redirects or resolves to localhost. Flamelink will reject Webhook requests for any other URLs.

Valid example: https://api.my-service.io/incoming-webhook

Triggers:
Specify which events should trigger the webhook request. These events consist of a module and action, for instance, "content.create" - the "Content" module with the "Create" action. 

Select any number of events, but bear in mind that if you add additional filters (see below), those might not all be relevant for all modules and actions and would be filtered out and therefore not sent.

Filters:
If you need more fine-grained control for when an event should trigger a webhook request, add any number of additional filters that should ALL be satisfied for the requests to send. (They AND together and not OR)

You can, for instance, add 2 filters, one to ensure only content entries for the "production" environment as well as the "en-US" locale should trigger the request. All other content updates will then be ignored.

A filter consists of 3 parts: 

  • a property - the key of the field to read
  • an operator - (equals, not equals, greater than, starts with, etc)
  • and the value to check the property against.

You can add custom properties (names of the fields in your content) by entering it in the "Property" field. Otherwise, conveniently choose one of the pre-defined options.

TIP: Nested data can be read by using dot notation, e.g. _fl_meta_.schema.

Basic Authentication:
If your webhook endpoint is protected using basic auth, you can provide a username and password which will be sent along to your endpoint as the Authorization HTTP Request header.

Headers:
Optionally, add extra custom headers you need, and Flamelink will set them for each webhook requests.

Activity Log:
If this setting is enabled, Flamelink will store a log of all requests with their respective responses in your database. Click "View Log" from the Webhooks overview table to view the activity log for the particular webhook. 

Also, note that any errors will be logged here regardless of whether this setting is enabled or not.

Sign Requests:
To verify that webhook requests originated from the Flamelink servers, as opposed to a third-party, and have not been tampered with, you can optionally enable webhook signing. When enabled, Flamelink will set a signature header, x-flamelink-signature for each request that you can use to verify it.

Read more here.

Content Type:
Most HTTP services use "application/json", but if the service you are integrating with requires a different content type, Flamelink also provides the following options: "application/x-www-form-urlencoded", "text/plain", and "text/html". If you are not sure, leave the default option as-is.

Custom Payload:
You have the choice of either using the default payload (request body) that Flamelink sends or enable this setting to have full control over the payload sent to your Webhook endpoint. Some services require a unique payload structure - this lets you set it up to handle any structure.

When enabled, a new "Custom Payload Template" field will become available below it.

Read more about the custom template here.

NOTE: Currently, there is a limit of 100KB on the size of your webhook payload.

Testing & Activity Logs

The easiest way to test your Webhook configuration is to use a free service like webhook.site to generate a test URL for you to which you can send the requests. These services catch all HTTP requests sent to it and will give you all the details you need for the requests. This includes all the HTTP Request Headers and Request body (payload).

For convenience, there is also a "Send Test" button available from the Webhook Setup Form from within Flamelink. All the responses will be logged to the webhook's activity log. Test webhook requests will ignore any custom payloads since no actual data exist for the event.

Note: the "Send Test" button is only available for saved webhooks, regardless of whether it is enabled or not.

Did this answer your question?