# Webhooks



Webhooks bring efficiency and responsiveness to solution architectures, facilitating event-based flows among applications and services. In Socotra Insurance Suite, they are customized callbacks that allow external services to receive real-time notifications when specific events occur. This functionality enables seamless integrations that can react to changes as quickly as possible.

Managing Webhooks [#managing-webhooks]

You create a webhook with a `POST` request to the <ApiLink name="CreateWebhookRequest">Create Webhook</ApiLink> endpoint, specifying the URL and event types that pertain to the webhook. The endpoint will then receive an <ApiLink name="EventResponse" /> payload whenever the relevant event occurs. Webhooks and the [Event Stream](/configuration/general-topics/events) share the same <ApiLink name="EventResponse" /> structure to describe an event.

Failure Handling [#failure-handling]

You can define a failure handling strategy for each webhook, ensuring that the system responds in a preferable way if it encounters a problem posting messages to the webhook endpoint. Strategies revolve around these questions:

1. For which errors should the failure handling strategy apply?
2. Should an endpoint (`alertEndpoint`) receive failure notices?
3. Should the platform automatically retry on message delivery failure? If so, how many attempts (`1` to `10`, default `3`), and what should the time interval and pattern be (`linear` or `exponential`)?
4. Should the platform persist messages that fail to be delivered? These can be retrieved later via the [Diverted Events API](/api/events/diverted-events).

If no `failureHandling` is specified, the default strategy will apply:

```json
"failureHandling": {
    "triggers": [
        "4xx",
        "5xx",
        "timeout"
    ],
    "divert": false,
    "suspend": false
}
```

The default specifies no <ApiLink name="RetryStrategyCreateRequest">retry strategy</ApiLink> or <ApiLink name="CreateEndpointRequest">alert endpoint</ApiLink> and does not automatically suspend the webhook, nor does it divert failed messages for later pickup via the [Diverted Events API](/api/events/diverted-events). It effectively means "behave with indifference as to whether message delivery succeeds".

The `triggers` array can be populated with specific 400- or 500-level HTTP codes, or all in those levels (`"4xx"`, `"5xx"`). The special keyword `"timeout"` is also recognized.

If `suspend` is set to `true`, it means that the webhook will be suspended automatically if it exhausts all retry attempts while trying to deliver a message. If no retry strategy is specified, no retry attempts will be made, and the webhook will be suspended following the first failure. Webhook suspension will result in an event being posted to the `alertEndpoint` if one has been configured, and subsequent messages diverted if the `divert` property is set to `true`. Webhooks can be unsuspended with the <ApiLink name="unsuspendWebhook">unsuspend endpoint</ApiLink> endpoint.

When defining a retry strategy, you may set the `type` to `linear` or `exponential`. While `linear` results in a request being made at a constant frequency specified by the `interval` (in milliseconds), `exponential` means that the wait period between retry attempts will grow as defined in the equation `{interval}} + {attempt}^4`.

<Callout>
  The timeout on a webhook is 10000 milliseconds.
</Callout>

<span id="webhooksSecurity" />

Security Features [#security-features]

`https://` <ApiLink name="CreateEndpointRequest">endpoints</ApiLink> can be configured with the following:

* A [secret`to be used in an HMAC signature (see`RFC 2104 - Keyed-Hashing for Message Authentication ](https://datatracker.ietf.org/doc/html/rfc2104)) that will be supplied in the `socotra-signature` header of messages sent to that endpoint.
* A `tag` to label which `secret` is currently in use. Must be between 2 and 32 characters, inclusive.
* An `hmacEnabled` flag that determines whether the `socotra-signature` should be derived and sent in message headers.
* A `secureSSL` flag that toggles TLS certificate verification. It is `true` by default.

`secret` can only contain alphanumeric characters and underscores, with a length between 8 and 64 characters.

The `tag` is optional, intended as a convenience that can facilitate secret rotations by ensuring that message recipients can easily identify which secret was used to generate the signature value. Even if there are in-flight messages using an old shared secret when you update the secret on the Socotra platform (with a new tag), your receiving code can identify those by the prior `tag` and use the corresponding prior secret value to verify the signature.

<Callout>
  The ability to disable TLS certificate verification is provided for testing and configuration purposes. It should not be left as `false` in production systems handling real customer data.
</Callout>

Signature Verification [#signature-verification]

The `socotra-signature` header takes the following form:

```
socotra-signature: t=<timestamp>,v1=<signature>,tag=<tag>
```

* `timestamp` is the UTC timestamp associated with the event transmission, in milliseconds.
* `signature` is the SHA-256 HMAC-hashed signature of the concatenated values `timestamp.JSONpayload.tag`. If there is no tag associated with the shared secret, then the value is derived from `timestamp.JSONpayload`.
* `tag` is the optional tag name supplied in `SecuritySpecification` as a label for the current shared secret.

For verification, the signature derivation can be performed with standard cryptographic library functions in all popular programming languages. Below is an example in JavaScript:

```javascript
const crypto = require('crypto');

const secret = 'abracadabraabracadabraabracadabraabracadabraabracadabra';

const timestamp = '1695835536124';
const jsonPayload =
	'{"id":"20012343863","transactionId":"254cb37e-43c4-4102-845a-fbfc5978537d","timestamp":1695835536078,"data":{"username":"alice.lee"},"type":"login.success","username":"alice.lee"}';
const tag = 'secret-1';

const algorithm = 'sha256';
const hmac = crypto.createHmac(algorithm, secret);

hmac.write(`${timestamp}.${jsonPayload}.${tag}`);
hmac.end();

const hash = hmac.read().toString('hex');
console.log('HMAC: ', hash);
```

See Also [#see-also]

* [Events](/configuration/general-topics/events): List of events and data structures
* [Webhook API reference](/api/configuration-and-development/webhooks): Details on creating, reading, listing, updating, and deleting webhooks
