---
title: "Create a lead"
method: POST
path: "/api/v1/leads"
tags: ["Leads"]
---

# Create a lead

`POST /api/v1/leads`

## Request

- Base URL: `https://app.relaw.ai`
- URL: `https://app.relaw.ai/api/v1/leads`
- Auth: HTTP bearer

Creates a lead and its first matter, then scores it, notifies the
firm, and emits `lead.created` — the same path the firm's own
capture form takes.

Leads are matched by email within the original firm book. If it matches
someone the firm already has, the existing client is returned with
`deduped: true` and a 200 rather than a 201. That is a success:
treat it as the same person, not a conflict. It is also what makes
this endpoint safe to retry.

Requires a key with write access.

## Request body

- object
  - `firstName` string, required
  - `lastName` string, required
  - `email` string, email, required: Required, because it is a deduplication key. A lead with no email cannot be matched against existing clients.
  - `phone` string, required: Required contact number. Any format; normalized to E.164. Shared phone numbers do not merge people.
  - `leadSource` string: Free text shown to the firm as context, e.g. 'Google Ads'. Defaults to 'API'.
  - `address` string: Plain-text mailing address. Appended to this matter's private notes; does not change questionnaire answers.
  - `notes` string: Internal context or AI summary, appended to this matter's private notes. Existing staff notes are preserved; identical imported details are not appended twice. Not sent to the client or echoed in the response or lead webhook.
  - `message` string: Alias for notes. If both contain text, their trimmed values must be identical; otherwise the request returns 400.
  - `templateId` string, uuid: The intake form this lead answered. Defaults to the firm's lead capture form.
  - `utm` object
    - `source` string
    - `medium` string
    - `campaign` string
    - `term` string
    - `content` string

## Response `200`

Matched an existing client. `deduped` is true and no new client was created.

- LeadCreated
  - `id` string, uuid, required
  - `object` 'client', required
  - `firstName` string, required
  - `lastName` string, required
  - `email` string, nullable: Null is a real possibility, not an edge case — imported contacts often have no email. Do not assume this is present.
  - `phone` string, nullable: E.164.
  - `type` 'person' | 'organization'
  - `lifecycle` 'lead' | 'client' | 'former', required: `lead` has not been engaged; `client` is active; `former` is closed.
  - `leadSource` string, nullable
  - `leadScore` integer, nullable: 0–100, or null if not yet scored. Recomputed as engagement changes and as a lead goes cold, so it moves without the record changing.
  - `leadScoreBand` 'hot' | 'warm' | 'cold' | 'null', nullable
  - `attribution` object: First-touch, captured once on arrival and never overwritten.
    - `utmSource` string, nullable
    - `utmMedium` string, nullable
    - `utmCampaign` string, nullable
    - `utmTerm` string, nullable
    - `utmContent` string, nullable
    - `referrerHost` string, nullable
  - `createdAt` string, date-time
  - `matterId` string, uuid, required
  - `deduped` boolean, required: True when this matched an existing client rather than creating one.

## Other responses

- `201`: A new lead was created.
- `400`: Malformed request.
- `401`: Missing, malformed, revoked, or unknown API key.
- `403`: The key is read-only. Create a key with write access.
- `422`: Well-formed but rejected, e.g. an unnormalizable phone number.
- `429`: Over 120 requests per minute for this key. Honour the `Retry-After` header.

---

[API](https://skmtc.dev/relaw/apis/relaw-api.md) - [All operations](https://skmtc.dev/relaw/apis/relaw-api/llms.txt) - [OpenAPI document](https://skmtc.dev/relaw/apis/relaw-api/revisions/51a8e71983e0?raw)
