Skip to main content

Outbound Webhooks

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-Signature and X-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:

  1. Go to Settings > Webhooks

  2. Click the events log icon on the webhook row

  3. 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 whsec_ value; if regenerated, they need to update their server immediately

Deliveries showing 404

Endpoint URL is wrong or missing a path (e.g. /webhook)

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

  1. A firm administrator registers your endpoint URL in Lawmatics under Settings > Webhooks.

  2. When a subscribed event occurs, Lawmatics sends a signed HTTP POST to that URL.

  3. Your server verifies the signature and processes the event.

  4. You return a 2xx response 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

event_id

string

Unique ID for this event — use as an idempotency key

firm_id

integer

The Lawmatics firm that triggered the event

event_type

string

Event name (e.g. matter.converted)

version

string

Payload schema version (v1)

timestamp

ISO 8601

When the event occurred

data

object

Event-specific payload (see Events Reference below)

Request Headers

Header

Description

Content-Type

application/json

X-Lawmatics-Signature

HMAC-SHA256 signature — use to verify the request

X-Lawmatics-Timestamp

Unix timestamp (seconds) of when the request was sent

X-Lawmatics-Event-Id

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 secret

  • X-Lawmatics-Timestamp is the Unix epoch integer from the request header

  • Sign 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 2xx status 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 4xx response (other than 429) causes the delivery to be immediately abandoned with no retries — return 2xx even 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

matter_id

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].

Did this answer your question?