# Update a contact

Source: https://docs.emelia.io/docs/lists/update-contact

Guide: [Lists & contacts](https://docs.emelia.io/docs/lists.md)

`PATCH https://api.emelia.io/lists/contacts/{contactId}`

Updates a contact identified by its id only (its list is derived from the contact). The body is the same flat object as `POST /lists/list/{listId}/contacts`, with the same key resolution and the same pitfalls: unknown keys create custom variables, `null` and empty strings are ignored (a field cannot be cleared), sent fields overwrite, absent fields stay untouched. A company row is created if the contact has none and company fields are sent.

No duplicate check is made: changing the email to one already present in the list creates a duplicate. List counters are not updated. The campaigns using the list are resynchronized.

## Authentication

Send your API key in the `Authorization` header: `Authorization: <your API key>`.

## Path parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `contactId` | string | yes | Contact id (`leadId`). |

## Request body

Content type: `application/json`, required.

Flat contact object: one key per field, scalar values only. Standard keys are listed in the description of `POST /lists/list/{listId}/contacts`; any other key goes to an existing custom variable of the same name or creates a new one. Numbers and booleans are converted to strings. `null` and empty strings are ignored. Arrays and objects are rejected.

```json
{
  "jobTitle": "VP Sales",
  "phone": "+33612345678",
  "icebreaker": "Saw your post about the Series A"
}
```

## Example request

**cURL**

```bash
curl -X PATCH "https://api.emelia.io/lists/contacts/65f1a2b3c4d5e6f74db757ce" \
  -H "Authorization: $EMELIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "jobTitle": "VP Sales",
  "phone": "+33612345678",
  "icebreaker": "Saw your post about the Series A"
}'
```

**JavaScript**

```js
const response = await fetch('https://api.emelia.io/lists/contacts/65f1a2b3c4d5e6f74db757ce', {
  method: 'PATCH',
  headers: { Authorization: process.env.EMELIA_API_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "jobTitle": "VP Sales",
    "phone": "+33612345678",
    "icebreaker": "Saw your post about the Series A"
  }),
});
console.log(await response.json());
```

**Python**

```python
import os
import requests

response = requests.patch(
    "https://api.emelia.io/lists/contacts/65f1a2b3c4d5e6f74db757ce",
    headers={"Authorization": os.environ["EMELIA_API_KEY"]},
    json={
        "jobTitle": "VP Sales",
        "phone": "+33612345678",
        "icebreaker": "Saw your post about the Series A"
    },
)
print(response.json())
```

## Responses

### 200: Contact updated.

| Field | Type | Required | Description |
|---|---|---|---|
| `success` | boolean | yes |  |
| `leadId` | string | yes |  |
| `companyId` | string or null | yes |  |
| `createdCustomVariables` | array of object | yes |  |
| `createdCustomVariables[].technicalName` | string | yes |  |
| `createdCustomVariables[].displayName` | string | yes | The key as sent. |
| `createdCustomVariables[].schema` | enum: `lead`, `company` | yes | Always `lead` for variables created by the contact routes. |

```json
{
  "success": true,
  "leadId": "66f2a1b2c3d4e5f6a7b8c9d0",
  "companyId": "66f2a1b2c3d4e5f6a7b8c9e0",
  "createdCustomVariables": []
}
```

### 400: The contact id is not a valid ObjectId.

| Field | Type | Required | Description |
|---|---|---|---|
| `message` | string | yes | English, human-readable message. |
| `code` | string | no | Stable error code, when available (for example `PAYLOAD_TOO_LARGE`, `INVALID_JSON`, `export_too_large`, `companies_only`, `enrichment_running`). |
| `params` | object | no |  |
| `error` | string | no | Raw internal message (unexpected errors only). |

```json
{
  "message": "Invalid contact id"
}
```

### 401: Missing, unknown or disabled API key, or the account of the key no longer exists. Note the body shape: `error` and `code`, not `message`.

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | string | yes |  |
| `code` | enum: `AUTH_REQUIRED`, `ACCOUNT_NOT_FOUND` | yes |  |

```json
{
  "error": "string",
  "code": "AUTH_REQUIRED"
}
```

### 404: Contact not found, deleted, or not yours.

| Field | Type | Required | Description |
|---|---|---|---|
| `message` | string | yes | English, human-readable message. |
| `code` | string | no | Stable error code, when available (for example `PAYLOAD_TOO_LARGE`, `INVALID_JSON`, `export_too_large`, `companies_only`, `enrichment_running`). |
| `params` | object | no |  |
| `error` | string | no | Raw internal message (unexpected errors only). |

```json
{
  "message": "Contact not found"
}
```

### 413: JSON body larger than 5 MB.

| Field | Type | Required | Description |
|---|---|---|---|
| `message` | string | yes | English, human-readable message. |
| `code` | string | no | Stable error code, when available (for example `PAYLOAD_TOO_LARGE`, `INVALID_JSON`, `export_too_large`, `companies_only`, `enrichment_running`). |
| `params` | object | no |  |
| `error` | string | no | Raw internal message (unexpected errors only). |

```json
{
  "message": "Request body too large: the limit is 5mb",
  "code": "PAYLOAD_TOO_LARGE",
  "params": {
    "limit": "5mb"
  }
}
```

### 422: Invalid body (same messages as the add route).

| Field | Type | Required | Description |
|---|---|---|---|
| `message` | string | yes | English, human-readable message. |
| `code` | string | no | Stable error code, when available (for example `PAYLOAD_TOO_LARGE`, `INVALID_JSON`, `export_too_large`, `companies_only`, `enrichment_running`). |
| `params` | object | no |  |
| `error` | string | no | Raw internal message (unexpected errors only). |

```json
{
  "message": "Contact has no usable field"
}
```

### 500: Unexpected server error. `error`, when present, is a raw internal message: do not parse it. Retry later.

| Field | Type | Required | Description |
|---|---|---|---|
| `message` | string | yes | English, human-readable message. |
| `code` | string | no | Stable error code, when available (for example `PAYLOAD_TOO_LARGE`, `INVALID_JSON`, `export_too_large`, `companies_only`, `enrichment_running`). |
| `params` | object | no |  |
| `error` | string | no | Raw internal message (unexpected errors only). |

```json
{
  "message": "Hmm... Something went wrong. Please try again later."
}
```
