What crm.contact.add does
Creates a person record that deals, activities, and conversations bind to. In contact-centric integrations (bookings, e-commerce, subscriptions), resolving 'who is this person' correctly is most of the job.
Business use cases
- Customer records from e-commerce/booking checkouts
- Lead conversion flows in custom qualification systems
- Loyalty/membership system sync
- WhatsApp/chat integrations resolving message senders to people
Typical fields and parameters
NAME / LAST_NAME— At least one required in practice for usable recordsPHONE / EMAIL— Arrays of { VALUE, VALUE_TYPE } — your dedup keys, normalize before storingCOMPANY_ID— Primary company binding; multi-binding via crm.contact.company.items.setTYPE_ID— Contact type (client, supplier, partner) from the status directoryOPENED— 'Y' makes the contact visible to all users — decide your default deliberatelyUF_CRM_*— Membership numbers, external IDs, preferences
Example workflow
- Checkout completes with phone +91 98388 82505
- Phone normalized; crm.contact.list filtered by it (or crm.duplicate.findbycomm)
- Found → use existing ID; not found → crm.contact.add
- External customer ID stored in UF_CRM_EXT_ID both ways
- Deal created with CONTACT_ID binding
Example request
POST .../crm.contact.add.json
{
"fields": {
"NAME": "Priya",
"LAST_NAME": "Sharma",
"PHONE": [{ "VALUE": "+919838882505", "VALUE_TYPE": "MOBILE" }],
"EMAIL": [{ "VALUE": "priya@example.com", "VALUE_TYPE": "WORK" }],
"TYPE_ID": "CLIENT",
"OPENED": "Y",
"UF_CRM_EXT_ID": "CUST-77121"
}
}Example response
{ "result": 512, "time": { ... } }Field mapping notes
- Normalize phones to E.164 before both search and store — '+91 98388 82505' and '9838882505' must match
- Name splitting from single-string sources: put the full string in NAME rather than guessing surname boundaries wrong
- Store your system's customer ID on the contact AND the contact ID in your system — bidirectional keys make every future sync trivial
Security notes
- Contacts are personal data: minimal scopes, retention policy, and cross-visibility (OPENED) decided with the client
- Do not sync more personal fields than the CRM use case needs
Common errors
- Duplicate contacts multiplying — Search-before-create missing or phone normalization inconsistent — fix normalization first, then merge existing duplicates
- Contact created but invisible to team — OPENED='N' default with restrictive permissions — set OPENED='Y' or fix role visibility
- Company binding missing — COMPANY_ID must reference an existing company — resolve/create the company first
Production implementation tips
- Wrap resolve-or-create in a single idempotent function used by every integration — one implementation, one dedup policy
- Batch the search + create + bind sequence where volume matters
- Run a scheduled duplicate report (same phone, different IDs) as an integration health metric
Webhook or OAuth app?
Follows the parent integration's choice; contact resolution is usually a component, not a standalone integration.
Full decision guide: webhook vs OAuth app in Bitrix24.
When to use a queue worker
Serialize per-phone-number in the queue: two simultaneous checkouts by the same new customer will otherwise race and create duplicate records.
How Tech Titan can help
Tech Titan builds production Bitrix24 integrations around crm.contact.add and its siblings — with authentication, field mapping, queue workers, retry logic, duplicate handling, and structured logs as standard. If this method is on your critical path, bring the requirement to a free audit call and leave with an architecture sketch.