Lawfficient API
Leads

Create a lead

POST /api/leads: create a lead with a per firm API key.

POST /api/leads

Creates a lead. With a per firm API key (scope leads:write) the payload is validated, the lead lands in the firm's first active pipeline stage that isn't final (stages a firm retired are skipped), and the created lead is returned in full. A lead.created webhook fires.

Request body

JSON. first_name, last_name, and source are required, plus at least one of email / phone. A lead has to be reachable.

FieldTypeNotes
first_namestringRequired.
last_namestringRequired.
sourcestringRequired. Where the lead came from.
emailstringRequired if no phone.
phonestringRequired if no email.
assignee_idstring | nullOptional firm member (UUID) to assign.
dataobjectOptional contact fields, by key (case type, etc.). Unknown keys are ignored. See Fields in data.

Idempotency

Send an Idempotency-Key header to make a create safe to retry: a repeat with the same key returns the original lead instead of creating a second. Use a fresh unique value (e.g. a UUID) per logical create.

Idempotency-Key: 9d2b7c1e-5a4b-4c3d-8e2f-1a2b3c4d5e6f

Example

curl https://app.lawfficient.com/api/leads \
  -H "Authorization: Bearer $LAWFFICIENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9d2b7c1e-5a4b-4c3d-8e2f-1a2b3c4d5e6f" \
  -d '{
    "first_name": "Ada",
    "last_name": "Lovelace",
    "email": "ada@example.com",
    "source": "partner_referral",
    "data": { "caseType": "Family" }
  }'
201 Created
{
  "id": "3f8c1e2a-1b2c-4d5e-8f90-abcdef012345",
  "first_name": "Ada",
  "last_name": "Lovelace",
  "email": "ada@example.com",
  "phone": "",
  "source": "partner_referral",
  "status": { "key": "new", "name": "New" },
  "assignee_id": null,
  "archived": false,
  "created_at": "2026-06-24T10:00:00.000Z",
  "last_activity_at": "2026-06-24T10:00:00.000Z",
  "data": { "caseType": "Family" }
}

Errors use the error envelope: 422 invalid_request (e.g. no contact method, or an invalid data value), 403 insufficient_scope (the key lacks leads:write), 409 no_open_stage (the firm has no active pipeline stage that isn't final), 409 stage_retired (the landing stage was retired while the request ran; retry it).

Inbound ingestion shares this path. Authenticate with a per source ingestion key instead of an API key and POST /api/leads is the inbound webhook: it takes the source's mapped fields, dedupes on externalId, and returns { status, leadId }. See the lead ingestion spec.

On this page