CRM

Availableapp.erp.io/crm/pipeline/contacts

Contacts and companies

A contact is a person; a company is who they work for. Both carry the source that created them, which is the field most worth trusting.

Records
Contacts and companies
Custom fields
Yes, per workspace
Ingest
One webhook, one routing table
Duplicates
Merged manually

The records

A contact holds a person: name, addresses, phone, their company, their history with you, and where they came from. A company holds an organisation and rolls up its contacts, opportunities and activity. Custom fields are configured per workspace at /crm/settings/fields, which is where you put the two or three things about a lead that actually decide whether you pursue it.

app.erp.io/crm/pipeline/contacts
Rachel Nkemdirim

Meridian Group · added 9 Mar from portal signup

SequenceNew opportunity
ActivityEmails6Opportunities1Fields
Replied to "Q2 introduction"

"Can you send pricing for 20 seats?"

2 days agoReply
Opened sequence step 2
4 days ago
Signed up on account.northwind.example
9 MarSource
A contact record. Source and first-touch are recorded automatically at ingest.

Lead ingest

There is one ingest endpoint and one routing table. A lead arrives with a source identifier; the routing table maps that identifier to a workspace; the lead is created there. Everything else — portal signups, Phony calls, your own forms — goes through the same path, which is why there is only one place to look when a lead does not appear.

Do not add the module mount to the webhook URL yourself

The ingest URL is given to you complete. Appending /crm to it — a natural thing to do, since the module is mounted at /crm — produces a path that 404s silently on the sending side, and the symptom is leads that simply never arrive. Use the URL exactly as issued.

A lead with no source identifier routes to a default

If the identifier is missing or empty, the routing table cannot place it and the lead lands in the fallback workspace rather than being rejected. It is not lost, but it is in the wrong place, and nobody looking at the right workspace will see it. Always send the identifier.

Check the routing table

At /crm/settings — it maps a source identifier to a workspace.

Send the identifier with every lead

It is the only thing that decides where the lead lands.

Use the URL as issued

No added path segments.

Watch the fallback workspace

Anything in it arrived without a valid identifier and tells you which integration is misconfigured.

Duplicates and merging

The same person arriving from two sources creates two contacts if the email addresses differ. Merging is manual and deliberate: an automatic merge on a fuzzy name match is the sort of thing that quietly joins two customers into one, and unpicking that is worse than the duplicate.

  • Merge from the contact record; the surviving record keeps both histories.
  • Companies merge the same way and their contacts follow.
  • A merge is recorded in the workspace audit log.
  • The usual cause of duplicates is a personal address on one form and a work address on another — worth a required field rather than a cleanup habit.

What this does not do

No automatic deduplication

Duplicates are surfaced, not merged. Deliberately.

No data enrichment

Nothing appends firmographic data from a third-party provider.

No contact-level permissions

Anyone in a workspace sees everything in it. Separation is by workspace.

No bulk import screen

Imports run through the API.

Questions

Can one contact belong to two companies?

No. One company per contact; move them if they change jobs and the history follows.

Where does "source" come from?

The ingest identifier, recorded at creation and never overwritten.

Can we require a field?

Yes, per workspace, in Settings → Custom fields.