Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ArnasDon/wacrm/llms.txt
Use this file to discover all available pages before exploring further.
Every inbound WhatsApp message in Wacrm is tied to a Contact record. The Contacts page gives you a searchable, paginated table of everyone who has ever messaged your number — or who you have imported manually. From here you can add tags, fill custom fields, leave internal notes, view linked conversations and deals, and bulk-manage your list.
Each contact is represented by the following fields:
| Field | Type | Description |
|---|
id | string | UUID primary key. |
phone | string | The WhatsApp phone number as stored (typically E.164, e.g. +15551234567). |
phone_normalized | string? | Digits-only form of phone, generated by the database (migration 022) and unique per account. Read-only — used for deduplication. Present on rows created after migration 022. |
name | string? | Display name. Optional; rendered as “Unnamed” in the UI when absent. |
email | string? | Email address. |
company | string? | Company or organisation name. |
avatar_url | string? | URL to the contact’s avatar image. |
tags | Tag[]? | Hydrated tag array — present when the query embeds contact_tags(tags(*)). |
created_at | string | ISO 8601 timestamp of when the contact was created. |
updated_at | string | ISO 8601 timestamp of the last update. |
Deduplication
Wacrm prevents duplicate contacts at the database level. Migration 022 adds a phone_normalized generated column that strips every character except digits from the phone value. A unique constraint is placed on (account_id, phone_normalized), so two rows with +1 555-123-4567 and 15551234567 are treated as the same contact.
What happens on import or API create:
- If you import a CSV row or call
POST /api/v1/contacts with a phone number that already exists in your account, the operation updates the existing contact’s name, email, and company fields rather than creating a duplicate.
- The API returns the updated contact with HTTP
200 for an existing match, or the new contact with HTTP 201 for a freshly created row.
This means you can re-import a CSV after enriching it with extra data and only new contacts will be created — existing ones are safely updated.
Tags are colored labels that can be attached to any number of contacts. They are created inline from the contact form or the contact detail view and are stored in the tags table with a name and a hex color.
Tag capabilities:
- A contact can have multiple tags simultaneously.
- Tags are displayed as colored pill badges in the contacts table, the inbox conversation list, and the contact sidebar.
- The contacts page has a Filter by tags popover that performs an OR filter — showing all contacts that have any of the selected tags. This filter resolves server-side using the
filter_contacts_by_tags RPC (migration 025) for correctness and performance on large lists.
- Tags are available as a filter parameter on the public API:
GET /api/v1/contacts?tag=<tagId>.
Use tags to segment contacts for targeted broadcasts and automation triggers. For example, tag high-value leads as VIP and then use that tag as a recipient filter when launching a broadcast, or as a tag_added automation trigger to kick off a follow-up sequence automatically.
Custom fields
Beyond the built-in fields, admins can define account-level custom fields in Settings → Custom Fields. Custom fields are defined by:
| Field | Description |
|---|
field_name | The label shown in the contact form and detail view. |
field_type | The input type: text, select, or other supported types. |
field_options | A JSON object carrying extra configuration (e.g. the list of options for a select field). |
Once a custom field is defined, it appears in every contact’s detail view where agents can fill in a per-contact value (ContactCustomValue). Custom field values are stored as strings and support {{ vars.* }} interpolation in automation steps.
Internal text notes can be added to any contact from the contact detail view. Notes are attributed to the agent who wrote them (user_id) and timestamped. They are visible to all team members but are never sent to the customer.
Notes complement the internal-note feature in the inbox: inbox notes are attached to a specific conversation, while contact notes are attached to the contact and visible regardless of which conversation is open.
CSV import
Use the Import button on the Contacts page to bulk-import contacts from a CSV file. The importer accepts the following columns:
phone,name,email,company
+15551234567,Alice Smith,alice@example.com,Acme Corp
+15559876543,Bob Jones,,
phone is the only required column; all others are optional.
- Rows whose
phone matches an existing contact are treated as updates (see Deduplication above).
- Invalid rows (e.g. missing phone, malformed CSV) are skipped and reported back to the user after the import completes.
API access
Contacts are fully accessible via the public REST API using a scoped API key.
| Scope | Permitted operations |
|---|
contacts:read | GET /api/v1/contacts — list contacts (paginated, with ?search= and ?tag= filters) |
contacts:write | POST /api/v1/contacts — create or update a contact by phone number |
See the Contacts API reference for full request and response schemas, pagination details, and code examples.