Integrations

Webhooks

Send every qualified lead and booking to any CRM or backend. Available on Firm Intake Pro and above.

How delivery works

Delivery
HTTPS POST with a JSON body (Content-Type: application/json). Plain http and private network addresses are refused, and redirects are not followed.
Response
Reply with any 2xx status within 5 seconds.
Retries
Failed deliveries are retried with backoff, up to 5 attempts. A retry carries the same payload.
Signature
X-Basalix-Signature: sha256=<hex>, an HMAC-SHA256 of the raw request body, keyed with the signing secret shown on your Webhooks card in the app.
Event name
X-Basalix-Event: <event name> (also in the body's event field).
Status
The last delivery result is shown on your Webhooks card; use Send test to check your endpoint.
Plans
Firm Intake Pro and above

Envelope

Every event has the same envelope.

eventThe event name.
sent_atISO 8601 timestamp (UTC).
tenant_idYour workspace ID.
project_setting_idThe agent that handled the conversation.
conversation_idShared by every event from one conversation.
channel"voice" or "chat".
dataEvent-specific fields (below).

Events

EventWhen it's sentFields in data
matter.qualifiedOnce per conversation, when a legal intake is qualified and the conversation is complete: at call end for voice; immediately for a chat callback or referral; on booking (or after 15 minutes idle) for a chat that books. Declined matters (already represented, out of scope) are never sent.name, email, phone, case_summary, intake, routing, routing_label, status, status_label, booking, matter_url
appointment.bookedA consultation is booked.appointment_id, service, staff, starts_at, ends_at, customer {name, phone, email}
appointment.rescheduledA consultation is moved.appointment_id, service, new_starts_at, new_ends_at
appointment.cancelledA consultation is cancelled.appointment_id, service, was
lead.capturedA general lead is captured (non-legal agents).name, email, phone, interest, organization, remarks
test.eventYou press Send test.message

A booked legal intake sends both appointment.booked and matter.qualified. Match them on conversation_id.

Example: matter.qualified

{
  "event": "matter.qualified",
  "sent_at": "2026-09-21T03:04:12.118Z",
  "tenant_id": "6e129126-7c41-4206-86b2-9bf2686fc3b6",
  "project_setting_id": "3f6c1e2a-8d4b-4c1f-9a7e-2b5d8c9e0f11",
  "conversation_id": "retell:call_8f2c41d9e7",
  "channel": "voice",
  "data": {
    "name": "Jordan Ellis",
    "email": "jordan.ellis@example.com",
    "phone": "+15125550148",
    "case_summary": "Jordan Ellis called about a rear-end collision on I-35 in Austin on September 17. The other driver was cited. Jordan has neck pain and was seen at urgent care the next day. Not represented by another attorney.",
    "intake": {
      "practice_area": "Personal injury",
      "jurisdiction": "TX",
      "incident_date": "September 2026",
      "injury_severity": "moderate",
      "liability_clear": "yes",
      "insurance": "Other driver insured",
      "represented": false,
      "sol_urgent": false,
      "sms_consent": true,
      "answers": { "police_report": "yes", "medical_treatment": "urgent care, 1 visit" }
    },
    "routing": "book_consult",
    "routing_label": "Book consultation",
    "status": "booked",
    "status_label": "Consultation booked",
    "booking": {
      "when": "Mon 21 Sep 2026, 10:30 AM",
      "service": "Initial consultation",
      "staff": "Daniel Rivera",
      "office": "Austin – Downtown"
    },
    "matter_url": "https://app.basalix.ai/agent/intakes/…"
  }
}

Fictional example. Field values vary with your intake template.

Field notes

  • incident_date is month and year only.
  • represented, sol_urgent and sms_consent are true, false, or null when the question wasn't asked.
  • answers holds your own intake-template questions; unanswered ones are left out.
  • routing is one of book_consult, attorney_callback, decline_referral, decline_out_of_scope. status is one of new, callback, booked, referred.
  • booking is null when nothing was booked.
  • case_summary can be null if no transcript was available.
  • matter_url opens the matter in your dashboard and requires sign-in.

Verify the signature

const crypto = require('crypto');
const expected = 'sha256=' + crypto.createHmac('sha256', SIGNING_SECRET).update(rawBody).digest('hex');
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.get('X-Basalix-Signature')));

Compute it over the raw request body, before any JSON parsing.

Connect with Zapier

Create a Zap with a "Catch Hook" trigger, paste its URL as your webhook URL in Basalix, and map the fields to your CRM.

Firm Intake Pro and above

Wire it into your stack.

14-day free trial. No credit card, nothing auto-charges.