## UpsertContacts

### cURL

```bash
curl --request POST \
  --url https://api.heylibby.com/api/v1/campaigns/{campaignId}/contacts \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '
{
  "contacts": [
    {
      "firstName": "Ava",
      "lastName": "Lopez",
      "email": "ava@example.com",
      "phone": "15551234567",
      "contactMetadata": {
        "source": "web_form",
        "tier": "trial"
      }
    }
  ],
  "action": "upsert"
}
'
```

### Response

**200**

```json
{
  "message": "Processed 3 contacts successfully",
  "success": [
    {
      "phone": "15551234567",
      "email": "jane.doe@example.com",
      "action": "created"
    },
    {
      "phone": "15559876543",
      "email": "john.smith@example.com",
      "action": "updated"
    }
  ],
  "errors": []
}
```

### Authorizations

#### x-api-key

- **Type**: string  
- **Location**: header  
- **Required**: yes

### Path Parameters

#### campaignId

- **Type**: string<uuid>  
- **Required**: yes  
- **Description**: The unique ID of the campaign

### Body

- **Content-Type**: application/json

#### contacts

- **Type**: object[]  
- **Required**: yes  
- **Description**: List of contacts to add or update. When `action` is set to `"remove"`, these contacts are removed from the campaign.

##### External Attributes
- **externalIdKey**: string (Optional) - Optional external ID name for this request batch.
- **externalIdValue**: string (Optional) - Optional external CRM value paired with root-level `externalIdKey` for routing in multi-assistant org-wide flows.

#### action

- **Type**: enum<string>  
- **Description**: Controls how contacts are processed.  
- **Available options**: `upsert`, `updateOnly`, `remove`.

### Response

**200**
- **Content-Type**: application/json

#### message

- **Type**: string  
- **Description**: Human-readable summary of the operation results.

#### success

- **Type**: object[]  
- **Description**: Contacts that were successfully created, updated, or deleted.

#### errors

- **Type**: object[]  
- **Description**: Contacts that failed to process with error details.
