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
POSTwith 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'seventfield).- 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.
| event | The event name. |
| sent_at | ISO 8601 timestamp (UTC). |
| tenant_id | Your workspace ID. |
| project_setting_id | The agent that handled the conversation. |
| conversation_id | Shared by every event from one conversation. |
| channel | "voice" or "chat". |
| data | Event-specific fields (below). |
Events
| Event | When it's sent | Fields in data |
|---|---|---|
| matter.qualified | Once 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.booked | A consultation is booked. | appointment_id, service, staff, starts_at, ends_at, customer {name, phone, email} |
| appointment.rescheduled | A consultation is moved. | appointment_id, service, new_starts_at, new_ends_at |
| appointment.cancelled | A consultation is cancelled. | appointment_id, service, was |
| lead.captured | A general lead is captured (non-legal agents). | name, email, phone, interest, organization, remarks |
| test.event | You 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 aboveWire it into your stack.
14-day free trial. No credit card, nothing auto-charges.