API v1: Contacts
List, create, update and delete contacts through the REST API, including custom fields and property-matching lookups.
Requires the contacts:read scope for reads, contacts:write for mutations.
List contacts
GET /api/v1/contacts
Also doubles as a "does this person already exist?" lookup — useful before creating a duplicate contact:
| Parameter | Description |
|---|---|
limit, cursor, sort, fields | Standard pagination (see API v1 reference) |
email | Exact, case-insensitive match on email OR secondary_email |
phone | Match on phone_number, normalized to E.164 (default region BG) before comparing |
q | Free-text ilike match across first_name, last_name, email |
curl "https://api.avensa.bg/api/v1/[email protected]" \ -H "Authorization: Bearer pk_live_xxx.yyy"
Get / update / delete a contact
GET /api/v1/contacts/{id}
PATCH /api/v1/contacts/{id}
DELETE /api/v1/contacts/{id}
Create a contact
POST /api/v1/contacts
Example (Zapier "Create Contact" action payload):
{
"first_name": "Maria",
"last_name": "Ivanova",
"email": "[email protected]",
"phone_number": "+359888123456",
"lifecycle_stage": "lead"
}
Response (201):
{
"id": "b2b1e6b0-...",
"account_id": "a1a1e6b0-...",
"first_name": "Maria",
"last_name": "Ivanova",
"email": "[email protected]",
"phone_number": "+359888123456",
"lifecycle_stage": "lead",
"lead_rating": null,
"budget_min": null,
"budget_max": null,
"owner_id": null,
"office_id": null,
"created_at": "2026-09-02T18:00:00.000Z",
"updated_at": "2026-09-02T18:00:00.000Z"
}
Contact fields (commonly used)
| Field | Type | Notes |
|---|---|---|
first_name, last_name | string | |
email, phone_number | string, nullable | phone_number is normalized to E.164 on write |
company_name | string, nullable | |
contact_type | enum, nullable | see CONTACT_API_TYPES |
lifecycle_stage | enum, nullable | lead, prospect, active_client, under_contract, won, leased, lost, dormant |
lead_rating | enum, nullable | hot, warm, cold |
source, purpose | string, nullable | |
budget_min, budget_max | number, nullable | |
owner_id, office_id | uuid, nullable |
Custom fields
POST/PATCH accept an optional custom_fields object (field_name → value), written through the account's custom field definitions. List the writable keys first:
GET /api/v1/custom-fields?entity_type=contact
Per-field write failures are non-fatal — the contact is still created/updated, and failures come back in custom_field_errors instead of failing the whole request:
{
"first_name": "Maria",
"last_name": "Ivanova",
"email": "[email protected]",
"custom_fields": {
"referral_source": "Facebook Ads",
"vip_tier": "gold"
}
}
{
"id": "...",
"first_name": "Maria",
"...": "...",
"custom_field_errors": [
{ "field": "vip_tier", "message": "Unknown custom field" }
]
}
Poll for changes
GET /api/v1/contacts/changes?since=2026-09-01T00:00:00Z
Returns recently modified contacts for polling-based sync — the pattern a Zapier trigger uses instead of a webhook.
Find contacts matching a property
GET /api/v1/contacts/matches?property_id={uuid}&min_score=40
Returns contacts whose saved search criteria match the given property, scored by the same engine that powers the in-app "Matching contacts" panel. Read-only, capped at 50 results, ordered by score descending. Each result carries match_score (0–100) and match_reasons.