CRM migration
Field-level mapping, validation, and rollback between PHP CRM and Twenty CRM. We move data and schema; workflows are rebuilt natively in Twenty CRM.
PHP CRM
Source
Twenty CRM
Destination
Compatibility
8 of 11
objects map 1:1 between PHP CRM and Twenty CRM.
Complexity
BStandard
Timeline
2-4 weeks
Overview
Moving from PHP CRM to Twenty CRM is a modernization path for teams on a self-hosted PHP stack that has not kept pace with active development or API documentation investment. PHP CRM exposes a REST API without published rate limits and stores file attachments on the local filesystem with no programmatic export path. Twenty CRM, built on TypeScript, Next.js, and NestJS, has over 40,000 GitHub stars, an actively developed REST and GraphQL API, and supports custom objects, field-level permissions, and workflow filters from its standard data model. We migrate by enumerating the source schema during discovery (PHP CRM allows user-defined field names per deployment), building the matching Twenty workspace schema, then loading records in dependency order with parent-record ID resolution. Attachments do not migrate programmatically; we export them to local storage for manual re-upload. Workflows and automations do not migrate as code; we deliver a written inventory for the customer admin to rebuild in Twenty's Workflow builder.
Every standard and custom field arrives verified.
AI proposes the map; you confirm before any record moves.
Parent–child, lookups, and ownership stay linked.
Calls, emails, meetings — with original timestamps.
Documents, uploads, and inline notes move with the record.
Why teams make this switch
Leaving
What's pushing teams away
Choosing
What's pulling them in
Object mapping
Each row shows how a PHP CRM object lands in Twenty CRM, including any object-level transformations, lookup resolution, or schema-design dependencies.
Typical mapping — final map is confirmed during the sample migration step.
PHP CRM
Contact
Twenty CRM
People
1:1PHP CRM Contact records map to Twenty People. We map standard contact fields (name, email, phone, address) directly and enumerate every active custom field present on the Contact object during discovery before writing any field mapping. The Twenty People object uses a flat address structure; PHP CRM address sub-fields (street, city, state, postal code, country) concatenate into the Twenty address fields. PHP CRM contacts linked to Companies receive a CompanyId lookup resolution after the Companies phase completes.
PHP CRM
Company
Twenty CRM
Company
1:1PHP CRM Company records map directly to Twenty Company. Company is migrated before People so that the Company relationship (WorkSpaces in Twenty) is available for resolution during People import. The Twenty Company object supports industry, employee count, annual revenue, website, and address fields mapped from equivalent PHP CRM fields. Custom fields on Company are enumerated during discovery and mapped field by field.
PHP CRM
Deal
Twenty CRM
Opportunity
1:1PHP CRM Deal records map to Twenty Opportunity. The deal name, value, expected close date, and owner assignment transfer directly. Deal stage names in PHP CRM map to Twenty pipeline stages, which we pre-create in the destination workspace before the Opportunity import phase. If PHP CRM has multiple pipelines, each becomes a separate Twenty pipeline.
PHP CRM
Pipeline
Twenty CRM
Pipeline
lossyPHP CRM pipeline definitions map to Twenty pipeline containers. We extract the pipeline list from the source instance during discovery and create matching Twenty pipelines with the same pipeline names. Pipeline creation in Twenty happens before any Opportunity records are imported so that stage assignment is valid at insert time.
PHP CRM
Pipeline Stage
Twenty CRM
Stage
lossyPHP CRM stage names and order map to Twenty Stage records under each Pipeline. We extract the actual stage list from the source instance, preserving the sequence order and probability percentages where present. Any stages with no matching Twenty stage name are flagged as unmapped and held for the customer admin to resolve before Opportunity import.
PHP CRM
Task
Twenty CRM
Task
1:1PHP CRM Task records map to Twenty Task. Due date, assignee, status, and linked entity (Contact, Company, Deal) transfer directly. We resolve the assignee by matching PHP CRM owner email to Twenty User during the Users phase. The linked entity reference (Contact, Company, or Deal) resolves after parent record IDs are established in the destination system.
PHP CRM
Note
Twenty CRM
Note
1:1PHP CRM Notes attach free-text content to any entity (Contact, Company, Deal). Notes migrate as Twenty Note records linked to the target entity (People, Company, or Opportunity) via the computed relationship mapping after parent records are established. Note body transfers as rich text where PHP CRM stores it; plain text note bodies migrate as-is.
PHP CRM
Activity
Twenty CRM
Task or Note
1:1PHP CRM Activity records track interactions (calls, emails, meetings) with timestamps and outcome data. Activity schemas vary by PHP CRM deployment. We enumerate the actual activity fields present in the source instance during discovery and map call activities to Twenty Task with TaskSubtype=Call, meeting activities to Twenty Event or Task, and email activities to Twenty Note or Task depending on whether the email body is substantive. We flag any activity fields with no Twenty equivalent during discovery for customer decision on retention or exclusion.
PHP CRM
Custom Field
Twenty CRM
Custom Field
lossyPHP CRM custom fields on standard objects map to Twenty custom fields on the equivalent standard objects (People, Company, Opportunity, Task). Each PHP CRM deployment has a unique custom field inventory; we run a mandatory discovery phase enumerating every custom field on every standard object before writing any field mapping. Custom field types (text, number, date, picklist, checkbox) map to typed Twenty fields, and any unsupported field types are flagged for the customer admin to address before migration.
PHP CRM
User / Owner
Twenty CRM
User
1:1PHP CRM user records map to Twenty User by email matching. Owners assigned to Deals and Tasks are resolved via the User mapping. Any PHP CRM owner without a matching Twenty User (inactive or deleted source users) is flagged in a reconciliation queue for the customer admin to provision before record import resumes.
PHP CRM
Tag / Label
Twenty CRM
Tag or Custom Field
1:1PHP CRM tags stored as multi-checkbox properties migrate to Twenty custom multi-select picklist fields on the equivalent standard object. Tag vocabulary is per-instance; we extract the full tag taxonomy from the source and map each distinct tag value to a Twenty picklist value or a separate Tag entity depending on how the customer intends to use tags post-migration.
| PHP CRM | Twenty CRM | Compatibility | |
|---|---|---|---|
| Contact | People1:1 | Fully supported | |
| Company | Company1:1 | Fully supported | |
| Deal | Opportunity1:1 | Fully supported | |
| Pipeline | Pipelinelossy | Fully supported | |
| Pipeline Stage | Stagelossy | Fully supported | |
| Task | Task1:1 | Fully supported | |
| Note | Note1:1 | Fully supported | |
| Activity | Task or Note1:1 | Fully supported | |
| Custom Field | Custom Fieldlossy | Fully supported | |
| User / Owner | User1:1 | Fully supported | |
| Tag / Label | Tag or Custom Field1:1 | Fully supported |
Gotchas + challenges
Platform-specific issues from each side, plus the pair-specific challenges that don't show up on either platform's page on its own.
PHP CRM gotchas
No publicly documented API rate limits or endpoints
Attachment and file storage not accessible via API
Custom field taxonomy varies per deployment
Workflows and automations are not portable
Limited review corpus for accurate benchmarking
Twenty CRM gotchas
Import order is enforced and critical
Export limited to 20,000 records and visible columns only
Soft-deleted records count toward uniqueness and trigger restores
API rate limits cap at 200 req/min on Organization tier
No native email sequences — follow-up cadences require external tools
Pair-specific challenges
Migration approach
Discovery and API access assessment
We audit the source PHP CRM instance by connecting to its REST API with provided credentials and enumerating the object schema, custom field inventory, pipeline definitions, stage lists, and user list. If API access is unavailable or unreliable, we fall back to CSV export via the admin panel. We document every custom field name, type, and picklist value; every pipeline and stage name; and every user with their email and active/inactive status. The discovery output is a written migration scope and a PHP CRM API accessibility report.
Twenty workspace schema provisioning
We provision the Twenty workspace schema before any data import. This includes creating Twenty Pipelines matching the source pipeline names, creating Stage records under each Pipeline with names and sequence order matching the source, creating any custom fields on standard objects (People, Company, Opportunity, Task) matching the enumerated PHP CRM custom field inventory, and setting field types (text, number, date, picklist, checkbox) to match the source data. Schema is provisioned via the Twenty API or admin interface into a staging environment first for validation.
Twenty User provisioning and owner reconciliation
We extract every distinct PHP CRM owner referenced on Deals, Tasks, and Activities and attempt to match by email against the Twenty destination workspace's User list. Owners without a matching Twenty User go to a reconciliation queue. The customer provisions any missing Twenty Users (active or inactive depending on whether the original PHP CRM user is still active). Owner resolution must complete before Deal and Task import can proceed because OwnerId is a required reference on both objects.
Sandbox migration and reconciliation
We run a full migration into the Twenty staging environment using production-like data volume. The customer's admin spot-checks 25-50 random records against the PHP CRM source, validates that parent-child relationships (Company to People, Company to Opportunity) are preserved, and signs off the schema and mapping before production migration begins. Any field mapping corrections, stage name adjustments, or custom field additions happen at this stage, not in production.
Production migration in dependency order
We run production migration in strict record-dependency order: Companies (parent entity), People (with CompanyId lookup resolved), Pipelines and Stages (created before Opportunities), Opportunities (with PipelineId, StageId, CompanyId, and OwnerId resolved), Tasks (with assignee and linked entity resolved), Notes (linked to People, Company, or Opportunity), and Activities (mapped to Task or Note depending on type). Each phase emits a row-count reconciliation report before the next phase begins. Attachments are exported to local storage for manual re-upload post-migration.
Cutover, validation, and workflow rebuild handoff
We freeze PHP CRM writes during cutover and run a final delta migration of any records modified during the migration window. We deliver the workflow inventory document listing every active PHP CRM automation with its trigger, conditions, and actions, plus an estimated rebuild time in hours for the Twenty Workflow builder. We support a one-week hypercare window where we resolve any reconciliation issues raised by the customer's team. We do not rebuild PHP CRM workflows as Twenty Workflows inside the standard migration scope; that is a separate engagement.
Platform deep dives
PHP CRM
Source
Strengths
Weaknesses
Twenty CRM
Destination
Strengths
Weaknesses
Complexity grading
Standard CRM migration. 3 of 8 objects need a mapping; the rest are 1:1.
Overall complexity
Standard migration
Derived from compatibility, mapping clarity, API constraints, and data volume across PHP CRM and Twenty CRM.
Object compatibility
3 of 8 objects need a mapping; the rest are 1:1.
Field mapping clarity
Field mapping is derived from defaults — final spec confirmed during the sample migration.
Timeline complexity
8-object category — typical timelines run 2–7 days end-to-end.
API constraints
PHP CRM: Not publicly documented.
Data volume sensitivity
PHP CRM doesn't expose a bulk API — REST + parallelization used for high-volume runs.
Estimator
Rule-based pricing — no per-record fees, no manual quotes. Migrations over 2M records are scoped individually.
Step 1
Pick a category, then your source and destination platforms.
Category
FAQ
Answers to the questions buyers ask most during PHP CRM to Twenty CRM migration scoping. Not seeing yours? Book a call.
Walk through your PHP CRM to Twenty CRM migration with a real engineer — 30 minutes, free, written quote within 24 hours.
Book a free 30 minute consultationAdjacent paths
Other ways to leave PHP CRM
Other ways to arrive at Twenty CRM
Ready when you are
Tell us record counts and timeline. We'll come back with a written quote inside 1 business day — no commitment, no sales pitch.