Webhooks

In addition to polling for the response to be available, Fonoa supports Webhooks to notify you once your request has been processed and the results are available.

Request

POST /webook-url
Content-Type: application/json
X-Fonoa-Hmac-SHA256: 5618fc91f4bea53c1203f3cea4fb69e526cc5ae566550cd754707c297fc93779

{
    "event_type": "lookup.batch_validation_completed",
    "delivered_at": "2006-01-02T15:04:05Z",
    "resource_id": "95afe365-7e3f-40e8-91fa-b3a4fd08eb68",
    "resource_url": "https://api.fonoa.com/lookup/v2/batch-validations/95afe365-7e3f-40e8-91fa-b3a4fd08eb68",
    "webhook_id": "875bd24499d303cbe8afb3db1987d8aa522d63bb"
}
Field nameDescription
event_typeThe event at Fonoa that triggered the Webhook. Usually this is a "completed" event for an operation.
delivered_atTimestamp of when Fonoa tried sending the Webhook. The format is RRC3339 and ISO8601 compatible, strictly in the format YYYY-MM-DDTHH:mm:ssZ and always in UTC timezone.
resource_idID of the resource that triggered the event.
resource_urlURL at which the full resource can be retrieved.
webhook_idIdempotency key for this webhook event. This needs to be treated as opaque string.

Getting started

To get started with using Webhooks, we recommend to first use our demo environment. Since usually the handling of incoming Webhhooks requests differs based on the event type, instead of providing a test event, we recommend to test all events the API client needs by triggering such an event (e.g. by calling the "Request a batch validation" endpoint to test "batch validation completed" events).

Configuration

We currently do not offer an automatic way of configuring Webhooks. Instead, please notify your contact at Fonoa that you want to start using Webhooks and let us know: - For which event(s) should Webhooks be configured - Which HTTPS endpoint the Webhooks should be delivered to. This can be either one URL for all event types, or one URL per event type.

Best practices

Idempotency

Fonoa does not normally make multiple requests for the same event on a resource, but does not guarantee only-once delivery of Webhooks. In addition, on HTTP error responses and timeouts (see retries section), the same notification is re-sent multiple times.

It is up to the API customer to decide on how to handle repeated webhook calls, but we do provide a field webhook_id in the payload that can be used as an idempotency key, as we guarantee the field to not change on retried notifications.

Message authentication

A third-party attacker with knowledge of the API client's Webhook URL(s) could attempt to send spoofed request to trick the client into accepting wrong data. All Webhook notifications are signed using HMAC SHA256, with the secret being the API key and the message being the JSON-encoded payload as sent by Fonoa. To prevent replay attacks, it is recommended to check the delivered_at timestamp.

It is recommended to verify the HMAC of incoming requests. Additionally, it is recommended to verify the resource_id matches a resource that the API client is aware of. If the resource_url field is used to determine where to fetch the full resource from, it is required to verify the HMAC of incoming requests to prevent an attacker spoofing resources.

As Fonoa is running on cloud infrastructure, we do not provide a list of outgoing IP addresses.

Javascript example of getting the expected signature

// the example is using crypto-js library (https://www.npmjs.com/package/crypto-js, version 4.x.x)
import hmacSHA256 from 'crypto-js/hmac-sha256';
import Hex from 'crypto-js/enc-hex';

const rawRequestBody = '{...}';
const apiKey = 'xxxx';
const expectedSignature = Hex.stringify(hmacSHA256(rawRequestBody, apiKey));

Errors and retries

Should a Webhook notification be undeliverable, either due to a connection error, or when receiving a HTTP response code in the HTTP Client Error (4xx) or HTTP Server Error (5xx) range, the notification will be retried up to 20 times with an exponential back-off. Retries will contain the same webhook_id (see Idempotency), but a different delivered_at timestamp.

Should an API client be unreachable for extended period of time, webhook notification might get discarded after multiple retries. It is recommended that an API client implements reconciliation functionality for those events by falling back to the polling approach for resources for which no webhook has been successfully received.

Redirects

If a request returns a HTTP Redirect (3xx) response code and a Location is specified, the redirect is followed up to 3 levels deep. Redirects to non-secure URLs are not followed. Should a redirect target return an error (see Errors and retries), the retry will again go to the configured URL.