Skip to main content

Setting up webhooks

Webhooks let Legl notify your systems in real time whenever something important happens — for example, when an Engage request is ready for review or a Risk Assessment is closed

L
Written by Luke Dailey

This article walks you through enabling webhooks, creating a configuration, and the options available to you.

Note: Webhooks are a self-service feature. You'll need an API key to use them — if you haven't generated one yet, see Generating an API key in the Settings area.


Before you start

You'll need:

  • Admin access to the Legl platform.

  • A receiving endpoint — a publicly accessible HTTPS URL on your side that can accept JSON POST requests and respond with a 2xx status.

  • A Legl API key for your firm. The same token is used to sign each webhook payload, so your endpoint can verify the request really came from us.


Where to find webhook settings

  1. Go to Settings → Integrations.

  2. Scroll to the Webhooks section.

  3. Click Add to create your first webhook configuration. You can have as many configurations as you need (for example, one for staging and one for production, or different endpoints per event family).


Creating a webhook

When you click Add, you'll see the following options:

Name (required)

A short label so you can recognise the configuration later — e.g. Production Engage events or Disbursements – staging. It's only used inside Legl and isn't sent in the payload. There must be no spaces in the name.

Webhook URL (required)

The HTTPS endpoint we'll send events to. It must:

  • Be reachable from the public internet.

  • Use HTTPS.

  • Respond with a 2xx status code within the delivery timeout (see below).

Event types

Tick each event you want this URL to receive. The full list is below — you can mix and match across products in a single configuration, or split them across multiple webhooks.

Active

A toggle that lets you pause delivery without deleting the configuration. When Active is off, no events will be sent to this URL, but the configuration and history are preserved. Useful while you're rolling out changes on your side.

Allowlist header value (optional)

If your firewall, WAF, or middleware needs an additional shared secret to allow the request through, paste a token here. Legl will include it on every request as the header:

X-Legl-Webhook-Token: <your token>

This is a simple shared-secret check; it does not replace verifying the Legl-Signature header (see Verifying webhook authenticity below).


Available events

You can subscribe to any combination of the events below. Each event has a stable identifier (used in the payload as event_type) and a human-readable name (shown in the settings UI).

Engage

Event

Fires when

engage_request_submitted

The client has completed and submitted all steps of an Engage request.

engage_request_ready_for_review

All processes are complete and the request is ready for a fee earner to review.

engage_request_reviewed

A user has reviewed the Engage request.

engage_request_document_completed

A signer has signed a document via the e-signature step (fires once per signer).

Businesses & company reports

Event

Fires when

business_created

A new business is created.

entity_created

An entity is created.

entity_updated

An entity is updated.

company_report_created

A company report PDF has been generated.

Risk assessments

Event

Fires when

risk_assessment_created

A new risk assessment is created.

risk_assessment_completed

A risk assessment has been completed.

risk_assessment_pdf_ready

The PDF for a completed risk assessment is ready to download.

risk_assessment_closed

An assessment is manually closed (e.g. the client stopped instructing).

risk_assessment_reopened

A previously closed assessment is reopened.

Sanctions & monitoring

Event

Fires when

business_sanctions_check_ready_for_review

A business sanctions report is ready for review.

business_sanctions_check_reviewed

A business sanctions report has been reviewed and is ready as a PDF.

business_sanctions_monitoring.configuration_changed

Business sanctions monitoring is disabled.

business_sanctions_monitoring.alert_status_changed

A business sanctions monitoring alert moves between action required and no action.

business_report_monitoring.configuration_changed

Business report monitoring is disabled.

business_report_monitoring.alert_status_changed

A business report monitoring alert moves between action required and no action.

individual_watchlist_monitoring.configuration_changed

Individual watchlist monitoring is disabled.

individual_watchlist_monitoring.alert_status_changed

An individual watchlist monitoring alert moves between action required and no action.

For the exact payload structure of each event, see our API reference — every event has a dedicated schema documenting each field.

See our implementation materials on our Postman page for more details if needed.


What a webhook delivery looks like

Every event is wrapped in the same envelope so your endpoint can route on event_type and use uuid for idempotency:

{
"uuid": "f1e2d3c4-b5a6-7890-1234-567890abcdef",
"event_type": "engage_request_reviewed",
"version": 1,
"created_at": "2026-05-05T14:32:11Z",
"data": {
"...": "event-specific payload"
}
}

Headers we send:

Header

Purpose

Content-Type: application/json

Body format.

Legl-Signature

HMAC-SHA256 signature of the JSON body — see below.

X-Legl-Webhook-Token

Only sent if you configured an Allowlist header value.


Verifying webhook authenticity

We sign every payload so you can confirm it really came from Legl. The Legl-Signature header is the HMAC-SHA256 of the raw JSON body, using your Legl API key as the secret.

Pseudocode:

expected = hmac_sha256(api_key, raw_request_body).hex()
if not constant_time_compare(expected, request.headers["Legl-Signature"]):
reject(401)

Important:

  • Compute the HMAC against the raw request body before any JSON re-serialisation — re-encoding can change whitespace and break the signature.

  • Always use a constant-time comparison (e.g. hmac.compare_digest in Python, crypto.timingSafeEqual in Node).

  • If you rotate your API key, the signing key rotates with it — update both ends together.


Responding to a webhook

  • Reply with any 2xx status code as soon as you've received the event. We treat that as success.

  • Do your heavy work asynchronously — long-running processing should happen after you've responded, otherwise you risk the timeout.

  • Use the uuid field to deduplicate. The same uuid is reused across retries, so you can safely ignore one you've already processed.

Retries

If your endpoint returns a 4xx or 5xx, times out, or is unreachable, Legl will retry the delivery up to 5 times with exponential back-off. After that the message is marked failed and won't be re-sent automatically.


Testing your webhook

Once you've saved a configuration, click Test webhook address next to it. Legl will send a small signed test payload ({"test": "data"}) to your URL and report back whether the request succeeded.

A successful test confirms:

  • Your URL is reachable from Legl.

  • TLS is set up correctly.

  • Your firewall / allowlist accepts our request.

  • (If configured) the X-Legl-Webhook-Token header is being sent as expected.

It does not verify your Legl-Signature validation logic — for that, we recommend triggering a real low-stakes event (e.g. submit a sandbox Engage request) and checking your server logs.


Editing or removing a webhook

  • Edit any field at any time — changes take effect on the next event.

  • Pause by toggling Active off. Events fired while paused are not queued for later delivery.

  • Remove to delete the configuration entirely.


Troubleshooting

Symptom

Common cause

Test request succeeds but real events never arrive

The configuration is inactive, or no event types are ticked.

All deliveries fail with timeouts

Endpoint is too slow — move processing to a background job and respond 2xx immediately.

Legl-Signature doesn't match what you compute

You're hashing the parsed/re-serialised JSON instead of the raw request body.

Requests blocked by your firewall

Add the Allowlist header value, or get in touch with our support team about other allowlisting options.

Duplicate events

Expected on retries — dedupe on uuid.

Delivery timeouts

Legl will wait for your endpoint to respond before treating the delivery as failed and queuing a retry. This wait defaults to 5 seconds.


Need help?

Drop us a message via Live Chat (bottom right of your screen) or email [email protected] and we'll be happy to help you wire things up.

Did this answer your question?