# POST /contacts

**Resource:** [Contacts](./contacts.md)  
**Scopes:** `contacts:write`  
**Write operation:** yes

Create a new contact. first_name is required; last_name is optional. Contacts without a last name render cleanly in automation templates via {{contact.display_name}} and {{contact.greeting}}. Empty or whitespace-only last_name values are stored as NULL. Set skip_automations: true to suppress the contact_created trigger -- recommended for historical imports.

## Parameters

| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `first_name` | body | string | yes | Contact first name. Trimmed on save. |
| `last_name` | body | string | no | Contact last name (optional). Empty or whitespace-only values are stored as NULL. In merge templates, prefer {{contact.display_name}} (falls back to first name when no last name) and {{contact.greeting}} ("Hi Paul" or "Hi there") over raw {{contact.last_name}}. |
| `email` | body | string | no | Email address |
| `phone` | body | string | no | Mobile number in E.164 format (e.g. +61412345678). MUST be a mobile number -- landlines will be rejected with a 400 error. Use the landline field for fixed-line numbers. |
| `landline` | body | string | no | Landline/fixed-line number in E.164 format (e.g. +61299991234) |
| `date_of_birth` | body | string | no | Date of birth in YYYY-MM-DD format (e.g. 1990-03-26). Used by the birthday messaging cron to send automated birthday emails/SMS. |
| `job_title` | body | string | no | Job title |
| `source` | body | string | no | Lead source (e.g. website, referral, api) |
| `notes` | body | string | no | Free-text notes |
| `metadata` | body | object | no | Custom field values as { field_id: value } pairs. Use GET /crm-settings to discover available custom fields. Reserved key: "quick_links" stores per-contact Quick Link URLs as { <type-uuid>: <url> } -- define types via PATCH /company/crm-settings. UUID-shaped keys at metadata root are rejected (400) -- Quick Link URLs must be nested under metadata.quick_links. |
| `address_line1` | body | string | no | Street address line 1 |
| `city` | body | string | no | City |
| `state` | body | string | no | State/province |
| `postal_code` | body | string | no | Postal/zip code |
| `country` | body | string | no | Country (default: Australia) |
| `skip_automations` | body | boolean | no | Set true to suppress the contact_created trigger. Use for historical imports. Default false. |

## Request example

```bash
curl -X POST \
  "https://api.trustpager.com/functions/v1/api/v1/contacts" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Paul",
    "email": "paul@example.com",
    "phone": "+61412345678",
    "source": "api"
  }'
```

## Response example

```json
{
  "data": {
    "id": "new-uuid-...",
    "public_id": "C-002",
    "first_name": "Paul",
    "last_name": null,
    "email": "paul@example.com",
    "phone": "+61412345678",
    "landline": null,
    "job_title": null,
    "source": "api",
    "created_at": "2026-04-20T08:00:00Z",
    "updated_at": "2026-04-20T08:00:00Z"
  },
  "meta": { "credits_remaining": 9499 }
}
```

---
Base URL: `https://api.trustpager.com/functions/v1/api/v1` — Auth: `Authorization: Bearer YOUR_API_KEY`