Sync crm_data_id back to CDP for CDP-originated contacts (Qontak One)
Jira Story: TF-3551 · Task: TF-3517 (linked via "Work item split", corrected direction verified) · Epic: TF-3500 (bucket item A6, CDP 26Q3 Engineering Initiatives — re-homed from TF-3477 on 2026-07-21) · Sibling: TF-3526 (chat_data, same root cause → prd)
Overview
When a user creates a contact from CDP, CDP pushes to CRM to create the matching CRM
contact — but CRM publishes nothing back carrying the newly created CRM contact id, so on the
CDP side contact.crm_data.id stays null/empty for every CDP-originated contact. The BI
team reports widespread null/empty crm_data_id for Qontak One clients' CDP-created customers,
breaking downstream CRM ⇄ CDP association. The field is only populated on the CRM→CDP sync path
(contact-service/internal/app/payload/contact_sync_request.go:105), which never fires for
CDP-originated contacts.
Fix (per TF-3517): CRM (qontak.com) publishes a reciprocal event after creating a
CDP-originated contact — carrying crm_data_id, qontak_customer_id, and company_sso_id —
gated to Qontak One tenants (unified_app = TRUE); CDP (contact-service) consumes it and sets
contact.crm_data.id, idempotently.
Open transport question: the Jira description proposes a new Kafka topic + CDP consumer, but
the team discussion (2026-07-17, Berlianto/Julio/Puji) converged on API/webhook over Kafka
("overkill" since only CDP consumes it), and the sibling TF-3526 was subsequently revised to
reuse the existing /contacts/create sync webhook. TF-3517's transport should be re-decided
against that precedent before build starts — including whether it shares TF-3526's
DefineTarget duplicate-contact risk.
Scope Changes
- Backend — CRM publish-back of
crm_data_id(qontak.com) + CDP ingestion intocontact.crm_data.id(contact-service). Qontak One tenants only; CRM-originated contacts unchanged.
8. User Stories + Acceptance Criteria
| User Story | Importance | Mockup / Technical Notes | Acceptance Criteria |
|---|---|---|---|
| [CRMSYNC-S01] — CDP-originated contacts get their CRM id linked back As the platform, I want CRM to send the created crm_data_id back to CDP whenever a Qontak One contact is created from CDP, so that CDP-originated contacts are fully associated with their CRM record and BI/downstream joins stop seeing null crm_data_id. | Must Have | Publisher gated by Team#unified_app? via Billing::GetSubscriptionDetail (qontak.com/app/models/team.rb:498-511). CDP write reuses the existing CrmData{ID} path (contact_sync_request.go:105). Transport (Kafka vs webhook) to be settled per the Overview note. | — Happy Path — • AC-1: Given a Qontak One tenant, when a contact is created from CDP, then CRM sends back crm_data_id + qontak_customer_id + company_sso_id and CDP sets contact.crm_data.id to the CRM contact id (no longer null/empty).• AC-2: Given a CRM-originated contact, when it syncs to CDP, then behaviour is unchanged (existing sync path untouched). — Guard-rail — • NEG-1: Given a non-Qontak-One tenant, when a contact is created from CDP, then no publish-back occurs and behaviour is unchanged. • NEG-2: Given a duplicate/replayed event for a contact whose crm_data.id is already set, when it is consumed, then CDP no-ops (never overwrites with a different id; logs a warning). |
Verification
Not started — TF-3517 is To Do as of 2026-07-21; CDP-side BE owner is Julio Jeffer (assigned on the board 2026-07-21). Sequenced in Sprint 2 directly under his Customer Segmentation P1 close-out. Cross-team: CRM squad owns the publish side; CDP squad owns the ingestion side. Contract (transport + payload schema) must be agreed and documented before build.