Outbound Webhooks allow Lawmatics to automatically notify an external server whenever something happens in your account. When a supported event occurs, Lawmatics sends a signed HTTP POST request to a URL you configure — your server receives the notification and can take action immediately.
This feature requires a developer or technical resource. Lawmatics handles the sending; your team handles receiving and processing. Available on Premium plans.
Overview
For the firm administrator setting up webhooks in Lawmatics.
Getting Started
Go to Settings > Webhooks and click Add New Webhook.
You'll need to provide:
Webhook Name — a label to identify this endpoint (e.g. "Matter Converted — Production")
Endpoint URL — the HTTPS URL your server is listening on. Must be HTTPS — HTTP is not accepted.
Event Type — select
matter.converted
Click Save. Your signing secret will be displayed — copy it immediately and share it with your developer. It will not be shown again.
The Signing Secret
Every delivery is signed so your server can verify it actually came from Lawmatics. The signing secret is what your developer uses to verify each incoming request.
Shown in full only once — at creation, or when regenerated
Your developer stores it on their server and uses it to verify each delivery
Lawmatics sends two signature headers with every request:
X-Lawmatics-SignatureandX-Lawmatics-Timestamp
If the secret is lost: Open the webhook, click Regenerate next to the signing secret field. A new secret is shown once. The old secret stops working immediately — your developer must update their server right away or deliveries will fail with a 401 error.
Enabling and Disabling a Webhook
New webhooks are enabled by default. To pause deliveries without deleting the webhook, toggle the Active switch off in the Edit Webhook panel. Toggle it back on to resume.
Viewing Delivery History
To check whether a webhook fired and what happened:
Go to Settings > Webhooks
Click the events log icon on the webhook row
Each event shows: status, event type, event ID, number of attempts, timestamp, and response code
Click any event row to see the full delivery detail — including the response body your server returned and a per-attempt breakdown.
Status labels:
Status | Meaning |
Queued | Waiting to be sent |
Delivered | Successfully received by your server (2xx response) |
Retrying | Failed at least once, still trying (up to 7 attempts) |
Failed | All 7 attempts exhausted — will not retry |
Retry Behavior
If a delivery fails, Lawmatics retries automatically:
Attempt | Delay |
1 | Immediate |
2 | ~15 seconds |
3 | ~1 minute |
4 | ~5 minutes |
5 | ~30 minutes |
6 | ~1 hour |
7 | ~2 hours |
A 4xx response (other than 429) is treated as a permanent failure — Lawmatics will not retry. After all 7 attempts fail, the event is marked Failed and will not be retried. There is no manual replay in the current version.
Limits
Up to 2 webhook subscriptions per event type per firm
Troubleshooting
Symptom | Likely cause | Fix |
Deliveries showing 401 | Signing secret mismatch | Have your developer confirm the correct |
Deliveries showing 404 | Endpoint URL is wrong or missing a path (e.g. | Have your developer confirm the exact URL their server is listening on, then update it in Settings > Webhooks |
Deliveries showing 502 | Server is down or unreachable | Your developer needs to verify the server is running and publicly accessible |
Webhook not receiving events | Webhook may be disabled | Check that the Active toggle is on in Settings > Webhooks |
"Already used in 2 webhooks" error | 2-subscription limit reached | Delete or disable an existing subscription before creating a new one |
Secret not copied in time | Secret is only shown once | Use Regenerate — developer must update their server immediately |
Developer Guide
How It Works
A firm administrator registers your endpoint URL in Lawmatics under Settings > Webhooks.
When a subscribed event occurs, Lawmatics sends a signed HTTP POST to that URL.
Your server verifies the signature and processes the event.
You return a
2xxresponse to acknowledge receipt.
Upon creation, a signing secret is displayed once. The firm administrator must securely share it with you. Store it in your environment:
LAWMATICS_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Payload Envelope
Every event uses the same envelope structure:
{
"event_id": "evt_550e8400-e29b-41d4-a716-446655440000",
"firm_id": 123,
"event_type": "matter.converted",
"version": "v1",
"timestamp": "2026-06-02T18:30:00.000Z",
"data": {
"matter_id": 456
}
}
Field | Type | Description |
| string | Unique ID for this event — use as an idempotency key |
| integer | The Lawmatics firm that triggered the event |
| string | Event name (e.g. |
| string | Payload schema version ( |
| ISO 8601 | When the event occurred |
| object | Event-specific payload (see Events Reference below) |
Request Headers
Header | Description |
|
|
| HMAC-SHA256 signature — use to verify the request |
| Unix timestamp (seconds) of when the request was sent |
| Unique event identifier — use for idempotency |
Verifying Signatures
Always verify the signature before processing a webhook. This confirms the request came from Lawmatics and the body has not been tampered with.
How the signature is constructed:
signed_payload = "<X-Lawmatics-Timestamp>.<raw_request_body>" signature = "sha256=" + HMAC-SHA256(secret, signed_payload)
Use the full
whsec_...string as the secretX-Lawmatics-Timestampis the Unix epoch integer from the request headerSign the raw JSON string — do not parse or re-serialize before signing
The resulting signature is hex-encoded and prefixed with
sha256=
Node.js
const crypto = require('crypto');function verifySignature(secret, timestamp, rawBody, signature) {
if (!signature || !signature.startsWith('sha256=')) return false;
const payload = `${timestamp}.${rawBody}`;
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
Ruby
require 'openssl'def verify_signature(secret, timestamp, raw_body, signature)
return false unless signature&.start_with?('sha256=')
payload = "#{timestamp}.#{raw_body}"
expected = 'sha256=' + OpenSSL::HMAC.hexdigest('sha256', secret, payload)
ActiveSupport::SecurityUtils.secure_compare(expected, signature)
end
Python
import hmac, hashlibdef verify_signature(secret, timestamp, raw_body, signature):
if not signature or not signature.startswith('sha256='):
return False
payload = f"{timestamp}.{raw_body}"
expected = 'sha256=' + hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
Use a constant-time comparison (e.g. crypto.timingSafeEqual, hmac.compare_digest) to prevent timing attacks.
Replay Attack Prevention (Recommended)
Reject requests where the timestamp is older than 5 minutes:
const MAX_AGE_SECONDS = 300;
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp)) > MAX_AGE_SECONDS) {
return res.status(400).send('Request too old');
}
Responding to Webhooks
Return a
2xxstatus code to acknowledge receipt.Respond within 10 seconds — Lawmatics enforces a 10-second total timeout. If processing takes longer, acknowledge immediately and handle the event asynchronously.
The response body is ignored.
A
4xxresponse (other than429) causes the delivery to be immediately abandoned with no retries — return2xxeven if you plan to process asynchronously.
Idempotency
Use event_id as an idempotency key. In rare cases (network issues, retries), your endpoint may receive the same event more than once. Deduplicate on event_id to handle this safely.
Events Reference
matter.converted — Fired when a matter is converted. The conversion process moves it from any status to Hired.
Field | Type | Description |
| integer | ID of the newly converted matter |
Use the matter_id to fetch full matter details: GET /v1/matters/{matter_id} — see Lawmatics API Docs.
More event types coming soon.
Testing Locally
Use ngrok to expose your local server during development:
ngrok http 3000 # Gives you: https://abc123.ngrok-free.app
Register that URL (with your path appended, e.g. /webhook) in the Lawmatics dashboard, then trigger a conversion in your staging account to fire a matter.converted event.
For questions or feedback, contact [email protected].





