# Create or update a lead

### Create or update a lead

`POST /api/v1/leads/upsert`

Operation ID: `upsertLead`

Matches on identity: when a LinkedIn or Instagram identity already belongs to a lead, the fields sent are patched onto that lead and it is returned as "matched"; otherwise a lead is created. Needs a LinkedIn or Instagram identity to match on. Same identity formats as POST /leads.

**Request body** (required)

- `identities` (object, required)
  - `linkedin` (string, optional): Public identifier (john-doe), /in/ path (/in/john-doe or in/john-doe), profile URL (https://www.linkedin.com/in/john-doe), or user id (ACoAAA…). Stored as the identifier, not the URL.
  - `instagram` (string, optional): Username (john-doe), handle (@john-doe), or profile URL (https://www.instagram.com/john-doe). Stored as the username without @.
- `timezone` (string, required)
- `firstName` (string, optional)
- `lastName` (string, optional)
- `companyName` (string, optional)
- `companyDomain` (string, optional)
- `jobTitle` (string, optional)
- `email` (string, optional)
- `imageUrl` (string, optional)
- `properties` (object, optional)

**200**: The created or matched lead.

- `status` ("created" | "matched", required): created: a new lead. matched: an identity already belonged to this lead, so the fields sent were patched onto it.
- `lead` (object, required)
  - `id` (string · uuid, required)
  - `firstName` (string | null, required)
  - `lastName` (string | null, required)
  - `companyName` (string | null, required)
  - `companyDomain` (string | null, required)
  - `jobTitle` (string | null, required)
  - `email` (string | null, required)
  - `imageUrl` (string | null, required)
  - `timezone` (string, required)
  - `identities` (object[], required)
  - `liveEnrollment` (object | null, required)
    - `campaignId` (string · uuid, required)
    - `campaignName` (string, required)
    - `status` ("active" | "waiting" | "completed" | "stopped" | "failed", required)
  - `createdAt` (string · date-time, required)
  - `updatedAt` (string · date-time, required)
  - `properties` (object, required)
  - `enrollments` (object[], required)
- `requestId` (string · uuid, required): Id of this request, for support and troubleshooting

**Errors**

- `400`: Bad request
- `401`: Unauthorized: missing or invalid API key
- `403`: Forbidden
- `404`: Not found
- `422`: Invalid request payload
