CRM data portability
How to move CRM data into and out of DripPulse using the starter record layer (accounts, contacts, leads, opportunities, activities).
Opportunity pipelines
Each organization has a default sales pipeline with ordered stages (for example Unassigned, Prospect, Qualification, …, Won, Lost). Opportunities reference that structure with UUIDs:
pipeline_id— row incrm.opportunity_pipelinespipeline_stage_id— row incrm.opportunity_pipeline_stagesstage_position— optional ordering within a Kanban column
Export and import JSON include those fields on each opportunity. The bundle does not list full pipeline definitions as a top-level array; on import, stages are resolved against your org’s default pipeline when IDs are missing. For a product overview and HTTP API for pipelines, see CRM opportunity pipelines & Kanban.
Scope and tenancy
All CRM rows are scoped to your organization. Every API request must include Authorization: Bearer <JWT or API key> that resolves to exactly one organization. You never see another tenant’s data.
Identifiers
- Internal UUID — Primary key in Postgres (
crm.*tables). Stable for the life of the row. - public_id — Human-readable string (for example
acct_…,cnt_…,opp_…,lead_…,act_…). Unique across the product. Use this in exports and integrations when you need a stable external reference. - external_system / external_id — Optional fields for mapping rows back to Salesforce, HubSpot, or your own warehouse.
Export (full bundle)
Request a JSON snapshot of all CRM entities for the current organization:
GET /api/v1/crm/export Authorization: Bearer <token>
The response includes version, exported_at, organization_id, and arrays: accounts, contacts, opportunities, leads, activities. Cross-references use public_id (for example account_public_id on contacts) so the file is portable between systems.
Import (upsert)
Send the same JSON shape (or a subset) to upsert records:
POST /api/v1/crm/import
Authorization: Bearer <token>
Content-Type: application/json
{ "accounts": [ … ], "contacts": [ … ], … }
- Rows with a matching
public_idin your organization are updated; newpublic_idvalues create new rows. - Processing order is accounts → contacts → opportunities → leads → activities so foreign keys resolve correctly.
- Activities reference
record_type(for exampleaccount,contact) andrecord_public_idof the parent row. - Each imported row is logged in
crm.change_eventswith event typeimported.
Change history
Creates, updates, soft-deletes, and imports append rows to crm.change_events. List them with:
GET /api/v1/crm/change_events
Optional filters: record_type, record_id (UUID). Use this for audits and migration reconciliation.
Soft delete
DELETE on CRM resources sets deleted_at; rows are not returned in default list views but remain in the database for export and audit unless you omit them from your own pipelines.
Dashboard
Signed-in users can open CRM in the app sidebar, manage opportunities on the Opportunities page (Kanban or table, pipeline selector), and use Import & export to download a file or upload a JSON bundle without calling the API manually.