Contacts
Keep a canonical record of every person you've ever talked to — with custom fields per channel, duplicate merging, and bulk CSV import — so every chat opens with context.
TL;DR
- What it is — the CRM's contact directory. Every chat links to a contact; every contact belongs to a channel-specific template that defines its custom fields.
- Who it's for — every inbox user benefits automatically. Admins use this module for bulk imports, merges, segmentation, and custom-field design.
- Top outcome — never start a conversation without the guest's history, and never send a campaign to the wrong audience because of dirty data.
At a glance
| Plan tier | All paid tiers. |
| Who can use it | Account Owners, Admins, and Users. |
| Channels | Contacts are scoped per channel (WhatsApp Official, WhatsApp Unofficial, Email, Web Chat), each with its own custom-field template. |
| Integrations | Contact fields feed Campaigns audience filters. Bulk Import uses the same import engine. |
| Top limits | 25 / 50 / 100 rows per page · 100 max per API fetch · 5,000 max per bulk-create request · 10 MB CSV file · phone 7 – 15 digits · country code 1 – 4 digits. |
| API | Yes — partner API for listing, fetching, bulk-creating, merging, and deleting contacts. |
How to find it
Sidebar → Contacts.
Direct URL: https://lodgestory.com/crm/contacts
Related settings: Settings → Contact Fields (/crm/settings/contacts) defines the custom-field templates used here. Different module — see Contact Fields.
Bulk import. A bulk-import dialog is available here on the Contacts page, and Bulk Import is a separate workspace module with a richer import-plus-schedule flow. The key difference: the Contacts dialog creates contact records, while the Bulk Import module creates chats (and can schedule a first message at the same time).
📸 [SCREENSHOT: contacts-nav.png — sidebar with Contacts highlighted]
What is Contacts?
The problem it solves
Every channel, by default, identifies a person only by a phone number or an email. WhatsApp gives you +91... and nothing else; email gives you an address and maybe a display name. Without a proper contact database, agents retype guest names into every reply, campaigns misfire to the wrong segments, and duplicates multiply across channels until the same guest has three different records.
Contacts is the single source of truth under every chat. It captures standard identity (name, phone, country code, email), lets you add channel-specific custom fields (booking reference, loyalty tier, VIP flag), supports CSV import with duplicate detection, and lets you merge duplicates by hand with an audited merge trail.
What you get
- One contact per person, per channel. Uniqueness is enforced by phone + country code.
- Custom fields per channel. Each channel has its own contact template. Fields can be text, email, number, phone, select, checkbox, date, or long text. Required flags are enforced.
- CSV bulk import with validation. Four-step wizard: Upload → Preview → Import → Results. Up to 5,000 contacts per request; invalid rows are flagged with their specific problem and returned in an error-report CSV.
- Filters and segmentation. Five built-in filter dimensions, plus custom-field filters with operators like contains, starts with, is empty, greater than, before.
- Merge duplicates. Pick a primary and any number of secondaries; choose which value wins per field; secondaries are removed; all linked chats move to the primary.
- Soft-delete only. Deleted contacts are hidden but preserved — no accidental hard loss.
How it's different
- Channel-scoped custom fields. Most systems use one global field list; here every channel defines its own, because a B2B email contact cares about different things than a B2C WhatsApp contact.
- Flexible fields without schema changes. Add, rename, or remove a custom field on a template without any migration step.
- Merge is transactional and surgical. Chat links move correctly to the primary; overlapping links (primary already linked to that chat) are dropped cleanly. No orphaned records, no duplicated chat-contact links.
Customer scenarios
- New property onboarding. Operator migrates from a legacy system. Uploads a 4,000-row CSV of past guests. The preview validates every row against the channel's template, flags malformed phones and duplicates, and imports the valid rows. Downstream campaigns can target these contacts immediately.
- Duplicate cleanup. A single guest appears three times — different spellings, slightly different phone formatting. An admin searches the name, opens all three, picks a primary, picks which fields win, and merges. Past WhatsApp chats from all three are now on one record.
- VIP segmentation. An admin adds a custom field VIP tier (None / Silver / Gold / Platinum) to the WhatsApp template. Front-desk flags top guests. A campaign targets VIP tier = Gold or Platinum via the custom-field filter.
How it fits with the rest of Lodgestory
Contacts is the guest record that Home shows in the right panel. Campaigns filter their audience on contact fields. Bulk Import is the chat-plus-schedule workspace that shares the underlying import engine. Contact Fields defines the templates. Tickets and Calls reference contacts indirectly via the chat.
📸 [SCREENSHOT: contacts-landing.png — contacts list with filters, columns, and bulk-action bar]
Core concepts
| Term | What it means |
|---|---|
| Contact | One record for one person on one channel. Standard fields (name, phone, email) plus any custom fields the template defines. |
| Linked chat | A link between a contact and a chat. One chat can only link to one contact; one contact can link to many chats. |
| Contact template | The custom-field list for contacts on a specific channel. Each channel has its own. |
| Custom field | A field on the template — text, email, number, phone, select, checkbox, date, or long text. Can be required. |
| Merge | Combining duplicate contacts into one, choosing which fields win and reassigning all linked chats to the primary. |
| Soft delete | Hiding a contact without hard-deleting it. Deleted contacts don't appear in lists or pickers. |
Quick Start — import contacts and merge duplicates in 5 minutes
Step 1 — Open Contacts
Sidebar → Contacts or https://lodgestory.com/crm/contacts.
Step 2 — Open the bulk import dialog
Click Bulk import at the top right. The four-step wizard opens.
📸 [SCREENSHOT: contacts-qs-2.png — bulk import wizard]
Step 3 — Upload a CSV
Pick the destination channel (this decides which template's custom fields map in). Download the Sample CSV to see the expected columns. Drag your CSV file onto the upload zone (10 MB max).
Step 4 — Review the preview
Rows are validated:
- First name is required.
- Phone must be 7–15 digits.
- Country code is 1–4 digits (defaults to
91if not provided). - Email must look like an email.
- Custom fields must match their declared types.
Use the Valid / Errors / All tabs to inspect results.
What you'll see next: a preview table with valid rows in green and invalid rows in red with the specific reason.
Step 5 — Import
Click Import. The wizard shows the progress and then displays the Results tab — counts of created, skipped duplicates, and errors, plus a download button for an error-detail CSV.
Step 6 — Merge duplicates
Back on the list, search for a guest you suspect is duplicated. Select two or more records; the bulk-action bar shows Merge. Pick the primary record; for each differing field choose which record's value wins. Click Merge.
What you'll see next: the primary record retained, secondaries hidden, and the primary now holding all linked chats.
How it works
When you upload a CSV, Lodgestory:
- Parses the file client-side and matches column headers to the standard fields and the template's custom fields.
- Validates every row (required fields, phone and country-code formats, custom-field types).
- On import, checks for existing contacts on the destination channel by phone + country code and skips duplicates.
- Inserts valid rows in batches and returns a results summary.
When you merge duplicates, Lodgestory:
- Validates that the primary isn't in the secondaries list.
- Moves every chat linked to a secondary to the primary (or drops overlapping links cleanly).
- Combines custom field values in the order you chose (primary → secondaries → your overrides).
- Applies any standard-field overrides you picked.
- Hides the secondaries (soft-delete).
Everything is applied atomically — if the merge fails validation, nothing changes.
Features in depth
Contacts list
Paginated table. Sortable by first name, last name, email, phone, created date, and updated date. Configurable columns: seven standard plus any custom field from any template in the organisation.
Default page size is 25; pick 50 or 100 if you prefer. Each request returns at most 100 rows.
Filters
Five built-in dimensions plus custom-field filters:
| Dimension | Options |
|---|---|
| Channel | Single-channel select — scopes to that channel's template |
| Has chats | Yes / No / All |
| Date range | Created after / Created before |
| Custom field | Any field from any template — operators: equals, not equals, contains, starts with, is empty, is not empty, greater than, less than, before, after |
| Search | Free text across first name, last name, phone, email |
Custom-field filters combine with AND.
Contact detail drawer
Click any row. Shows the summary (name, email, phone with country code), every custom field from the contact's template, a Linked Chats section, created / updated timestamps, and the creator.
Edit mode toggles inline edit for standard and custom fields. Save writes the change immediately.
Linked Chats supports Link chat (search and attach any chat in the organisation) and Unlink chat (remove the link without deleting either side).
Create dialog
Click + Create contact:
- Channel selector (required) — decides which template's custom fields appear.
- First name (required).
- Last name, phone, country code, email — optional.
- Custom fields from the selected template, with their own required-field rules.
Bulk import (wizard)
Four steps:
- Upload — pick the destination channel, download the sample CSV, drag-drop your file (10 MB max).
- Preview — row-by-row validation with normalisation (strips spaces and hyphens from phones; defaults country code to
91when missing). Three tabs: All, Valid, Errors. Within-file duplicates flagged here. - Importing — the system checks for existing contacts on the channel and skips duplicates while inserting new rows in batches.
- Results — counts of created, skipped duplicates, and errors, plus an error-detail CSV download.
Key limits:
- Max 5,000 contacts per import request.
- CSV ≤ 10 MB.
- Duplicate strategy: skip (default) or error-out on the first duplicate.
Merge contacts
Select two or more in the list → Merge in the bulk-action bar.
- Pick a primary — this record is retained.
- For every differing field, pick the winning value (primary, any secondary, or a manual override).
- Review the summary — how many secondaries will be hidden, how many linked chats will move, how many will be dropped for overlap.
- Confirm.
Delete (single and bulk)
Detail drawer → Delete, or bulk-select → Delete. Always soft — the contact is hidden and the chat links removed (the chats themselves remain). Transactional for bulk.
Custom-field filter builder
In the filters panel. Pick any field from any template, pick an operator, pick a value. Add more conditions for AND logic.
Linked Chats
Inside the contact drawer. Shows every chat ever linked to this contact, with channel, type, and last-message time. Click a row to open the chat in Home — useful when preparing for an outbound message or a call.
Roles and permissions
All authenticated users in the organisation can work with contacts:
| Action | Account Owner | Admin | User |
|---|---|---|---|
| View contacts | ✓ | ✓ | ✓ |
| Create a contact | ✓ | ✓ | ✓ |
| Edit a contact | ✓ | ✓ | ✓ |
| Delete a contact | ✓ | ✓ | ✓ |
| Merge contacts | ✓ | ✓ | ✓ |
| Link / unlink a chat | ✓ | ✓ | ✓ |
| Bulk import | ✓ | ✓ | ✓ |
| Configure contact templates (Settings) | ✓ | ✓ | ✗ |
Cross-module workflows
Migration from a legacy CRM
An admin exports past guests from a legacy system, renames columns to match the Lodgestory sample CSV, and imports in one pass. Errors flagged by the preview (malformed phones, missing required custom fields) are fixed in the CSV and re-uploaded. Valid rows land, duplicates are skipped. A bulk-delete of obvious test or junk rows cleans up.
Modules involved: Contacts → Bulk Import → Contact Fields.
Campaign targeting by custom field
Marketing wants to message VIP tier = Gold guests. They open Contacts, add a filter for the VIP tier custom field, confirm the segment size, and hand the list to a Campaign broadcast.
Modules involved: Contact Fields → Contacts → Campaigns.
Inbound message → contact auto-link
When a message arrives on a new phone number or email, Lodgestory creates or updates a contact automatically and links it to the chat. The new contact appears in your list the same way any other does. This module's job starts at viewing and editing that contact, not creating it from inbound messages.
Limits a user will run into
| Limit | Value |
|---|---|
| Bulk create per request | 5,000 rows |
| Rows per page (UI) | 25 / 50 / 100 (default 25) |
| Max per API request | 100 rows |
| CSV file max size | 10 MB |
| Phone digits | 7 – 15 |
| Country code digits | 1 – 4 |
| Custom fields per contact | No limit |
| Chats per contact | No limit |
Errors & FAQ
| You see | Likely reason | What to do |
|---|---|---|
| "Contact not found" | Wrong ID or already deleted | Verify the ID; note that soft-deleted contacts are hidden from lists |
| "Maximum 5000 contacts per request" | Upload over the cap | Split the CSV |
| "Primary contact cannot be in the secondary list" | Invalid merge input | Pick distinct primary and secondaries |
| "Primary contact not found" | Primary was deleted between selection and merge | Pick a different primary |
| "First name is required" | Missing required field at create | Fill in the first name |
| "File too large. Maximum size is 10MB." | CSV over the size cap | Split the CSV |
| "Missing required column: firstName" | CSV header mismatch | Use the sample CSV as a template |
| "No data rows found in CSV" | File has headers only | Add rows |
| "Failed to parse CSV" | Encoding or quoting issue | Re-export as UTF-8 with standard CSV quoting |
Frequently asked
How is duplication detected?
By phone + country code, scoped to the channel's template. Two contacts with the same phone but different country codes are not duplicates. Email isn't used as a duplicate key.
Why did my CSV import skip rows I thought were new?
Those rows had the same phone + country code as existing contacts on the destination channel, so they were skipped under the default Skip duplicates strategy.
Can I hard-delete a contact?
Not from the UI. Soft-deleted contacts are hidden from lists and pickers but preserved. Contact support for a permanent delete.
Why doesn't my new custom field show up in existing contacts?
New template fields are available for newly created or edited contacts immediately. Existing rows won't have a value until someone edits them.
I merged the wrong way — can I undo?
No automated undo. Secondaries are soft-deleted; support can restore them and then you can re-merge. Plan merges carefully on records with many linked chats.
Can I export my contacts?
The Contacts workspace page doesn't have a native export. Use Reports for a full CSV export with filters.
Why aren't contacts created automatically when a new message arrives?
They are — but by the inbound message-ingest path. This module is for managing contacts, bulk creation, and merges after the fact.
Related modules & next steps
- Home (Unified Inbox) — the contact record powers the guest-details panel.
- Contact Fields — define the per-channel custom-field templates used here.
- Bulk Import — the standalone workspace for chat creation and first-outbound scheduling.
- Campaigns — target segments using contact and custom-field filters.
- Reports — export contacts as CSV.
- Tickets — linked to contacts indirectly via the chat.
Updated about 4 hours ago