# Contacts API

Create, read, and update your contacts. Contacts are also created automatically when prospects message you through WhatsApp, Telegram, or email.

## List Contacts

```
GET /api/v1/contacts
```

Returns a paginated list of your contacts.

**Query Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | number | Page number (default: 1) |
| `limit` | number | Items per page (default: 20, max varies by plan) |
| `status` | string | Filter by status: `prospect`, `scheduled`, `applicant`, `renter`, `archived` |
| `role` | string | Filter by role: `prospect`, `tenant`, `landlord`, `property_manager`, `vendor`, `other` |
| `channel` | string | Filter by channel preference |
| `search` | string | Search by name, email, or phone |

**Response:**

```json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Jane Smith",
      "email": "jane@example.com",
      "phone": "+15551234567",
      "status": "prospect",
      "role": "prospect",
      "channelPreference": "whatsapp",
      "source": "telegram",
      "referralSource": null,
      "language": "en",
      "appliedAt": null,
      "createdAt": "2026-02-10T14:30:00Z",
      "updatedAt": "2026-02-10T14:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 87,
    "totalPages": 5
  }
}
```

## Get Contact

```
GET /api/v1/contacts/:id
```

Returns a single contact by ID.

## Update Contact

```
PATCH /api/v1/contacts/:id
```

Update contact fields. Send only the fields you want to change.

**Request Body:**

```json
{
  "status": "scheduled",
  "channelPreference": "email"
}
```

**Updatable Fields:**

| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Contact name |
| `email` | string | Email address |
| `phone` | string | Phone number |
| `status` | string | `prospect`, `scheduled`, `applicant`, `renter`, or `archived` |
| `role` | string | `prospect`, `tenant`, `landlord`, `property_manager`, `vendor`, or `other` |
| `channelPreference` | string | Preferred communication channel |
| `source` | string | Original source |
| `referralSource` | string | How they found you |
| `language` | string | Preferred language (ISO 639-1 code, e.g. `en`, `es`) |

## Create Contact

```
POST /api/v1/contacts
```

Create a new contact manually (e.g., from a CRM import or external lead source).

**Request Body:**

```json
{
  "name": "Jane Smith",
  "email": "jane@example.com",
  "phone": "+15551234567",
  "status": "prospect",
  "role": "prospect",
  "channelPreference": "whatsapp",
  "source": "crm_import"
}
```

**Required:** `name` + at least one of `email` or `phone`.

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `name` | string | — | Contact name (required) |
| `email` | string | — | Email address |
| `phone` | string | — | Phone number |
| `status` | string | `prospect` | `prospect`, `scheduled`, `applicant`, `renter`, or `archived` |
| `role` | string | `prospect` | `prospect`, `tenant`, `landlord`, `property_manager`, `vendor`, or `other` |
| `channelPreference` | string | — | Preferred communication channel |
| `source` | string | `api` | How the contact was acquired |
| `referralSource` | string | — | External referral source |
| `language` | string | `en` | Preferred language (ISO 639-1 code) |

Returns `201 Created` with `{ "data": <contact> }` and a `Location: /api/v1/contacts/:id` header. Supports `Idempotency-Key`.

## Delete Contact

```
DELETE /api/v1/contacts/:id
```

Soft-deletes a contact by setting its `deletedAt` timestamp. The contact will no longer appear in list queries but is retained in the database for compliance.

Returns `204 No Content` on success. Returns `404` if the contact does not exist or was already deleted.

## Notes

- **Soft delete** — contacts are never hard-deleted. The `DELETE` endpoint sets `deletedAt` rather than removing the record, preserving conversation history and audit trails.
- **Tenant-isolated** — you can only access contacts that belong to your account.
- Contacts created via API default to `source: "api"` — contacts from inbound messages get the channel name as source.
- **`appliedAt`** — read-only timestamp, auto-set when status changes to `applicant` and cleared when status moves away. Not settable via the API.
- **`role`** — categorizes the contact type: `prospect` (default), `tenant`, `landlord`, `property_manager`, `vendor`, or `other`. Independent of `status` — a landlord can also be a prospect in the pipeline. Contacts from pre-screening workflows default to `prospect`.
- **`notes`** — internal notes are not exposed via the public API. Use the dashboard to manage notes.
