Skip to main content
POST
Create a contact

Authorizations

Authorization
string
header
required

An org API key: Authorization: Bearer oak_….

Body

application/json
first_name
string | null
last_name
string | null
email
string | null
phone
string | null
Pattern: ^\+[1-9]\d{1,14}$
country
string | null
Pattern: ^[A-Z]{2}$
city
string | null
Required string length: 1 - 120
instagram
string | null
Pattern: ^[a-zA-Z0-9._]{1,30}$
origin
enum<string> | null

Top-level acquisition category — how a contact entered the CRM.

Set once at first touch and never overwritten: a contact who joins the waitlist (WEB) and later messages on WhatsApp keeps WEB; the channel they messaged on lives on their ContactHandle, not here. The category is a fixed, platform-owned vocabulary so analytics roll-ups, the AI prompt, and inbound auto-assignment stay stable across orgs. The specific named source within a category (e.g. "Waitlist", "SaaStr 2026", "WhatsApp") is org-customizable — see the contact_sub_origins table. NULL for legacy contacts whose origin predates this field. Replaces the old conversational- only ContactSource (WHATSAPP/INSTAGRAM/MESSENGER), which collapsed acquisition and channel into one field.

Available options:
SOCIAL,
ADS,
WEB,
EVENT,
REFERRAL,
OUTBOUND,
IMPORT,
MANUAL,
API,
OTHER
sub_origin_id
string | null
sub_origin_key
string | null
funnel_stage_id
string | null
owner_id
string | null
properties
Properties · object | null

Response

Successful Response

id
string
required
first_name
string | null
required
last_name
string | null
required
email
string | null
required
phone
string | null
required
country
string | null
required
city
string | null
required
instagram
string | null
required
messenger
string | null
required
whatsapp_username
string | null
required
origin
enum<string> | null
required

Top-level acquisition category — how a contact entered the CRM.

Set once at first touch and never overwritten: a contact who joins the waitlist (WEB) and later messages on WhatsApp keeps WEB; the channel they messaged on lives on their ContactHandle, not here. The category is a fixed, platform-owned vocabulary so analytics roll-ups, the AI prompt, and inbound auto-assignment stay stable across orgs. The specific named source within a category (e.g. "Waitlist", "SaaStr 2026", "WhatsApp") is org-customizable — see the contact_sub_origins table. NULL for legacy contacts whose origin predates this field. Replaces the old conversational- only ContactSource (WHATSAPP/INSTAGRAM/MESSENGER), which collapsed acquisition and channel into one field.

Available options:
SOCIAL,
ADS,
WEB,
EVENT,
REFERRAL,
OUTBOUND,
IMPORT,
MANUAL,
API,
OTHER
sub_origin_id
string | null
required
whatsapp_status
enum<string>
required

WhatsApp presence status for a contact's phone number.

A new contact starts as UNVERIFIED when a phone is on file or UNAVAILABLE when none is. The AI agent flips UNVERIFIEDVERIFIED on a successful send, or → UNAVAILABLE on a 404 / not-on-whatsapp response. Direct patching is not exposed; the write path is purely service-layer derivation.

Available options:
verified,
unverified,
unavailable
funnel_stage_id
string | null
required
owner_id
string | null
required
last_contacted_at
string<date-time> | null
required
created_at
string<date-time>
required
updated_at
string<date-time>
required
properties
Properties · object