CRM migration

Migrate from PracticeHub to Twenty CRM

Field-level mapping, validation, and rollback between PracticeHub and Twenty CRM. We move data and schema; workflows are rebuilt natively in Twenty CRM.

PracticeHub logo

PracticeHub

Source

Twenty CRM

Destination

Twenty CRM logo

Compatibility

100%

10 of 10

objects map 1:1 between PracticeHub and Twenty CRM.

Complexity

BStandard

Timeline

48–72 hours

Rollback included Accuracy guarantee Field-level validation

Overview

What this migration involves

PracticeHub stores practice-management data (patient/person records, appointments, practitioner assignments, treatment notes, and custom compliance fields) in a healthcare-oriented schema. Twenty CRM is a modern open-source CRM built on React, NestJS, and PostgreSQL, with standard objects for People, Companies, Opportunities, Notes, and Tasks — plus a fully extensible custom-object and custom-field model accessible through REST and GraphQL APIs. The migration maps PracticeHub patient and person records to Twenty's People object, appointment and treatment data to custom Activity records, and any custom fields to Twenty custom fields created via Settings → Data Model before import. Twenty's CSV import enforces an ordered dependency chain (Companies → People → Opportunities → Custom objects) that often requires splitting PracticeHub's flat exports into separate CSV batches. PracticeHub's API rate limit of 1 request per second governs extraction speed; a dataset of 30,000 records takes approximately 8.3 hours to pull. FlitStack sequences the migration so foreign-key relationships resolve correctly, runs a sample migration with field-level diff before committing the full run, and captures in-flight changes during a 24–48 hour delta-pickup window.

Field-level fidelity

Every standard and custom field arrives verified.

Schema-aware mapping

AI proposes the map; you confirm before any record moves.

Relationships preserved

Parent–child, lookups, and ownership stay linked.

Full activity history

Calls, emails, meetings — with original timestamps.

Attachments & notes

Documents, uploads, and inline notes move with the record.

Why teams make this switch

Two sides of the same decision

Leaving

PracticeHub logo

PracticeHub

What's pushing teams away

  • The 1 request per second API rate limit makes bulk data extraction painfully slow for practices with thousands of patient records to migrate.
  • Limited public pricing transparency and vague enterprise sales process frustrate small practices seeking quick cost comparisons.
  • Some users report that advanced billing and insurance claim workflows are less mature than dedicated EHR platforms.
  • Support responsiveness varies; smaller customer accounts report slower ticket resolution times.
  • The platform's breadth across compliance, scheduling, and patient engagement means no single feature set is as deep as purpose-built alternatives.

Choosing

Twenty CRM logo

Twenty CRM

What's pulling them in

  • Top open-source CRM on GitHub with 40.6K stars, giving teams full source code access and infrastructure ownership without per-feature licensing surprises.
  • Free self-hosting under AGPL-3.0 means unlimited users and custom objects for the cost of cloud infrastructure alone, typically $20–100/month.
  • Pricing page explicitly mocks competitors for charging add-on fees for API access, webhooks, and workflows — transparency that resonates with RevOps teams burned by Salesforce.
  • Unlimited custom objects and fields with no price impact, letting teams shape the data model to their business rather than forcing business into rigid schemas.
  • Modern TypeScript/React/PostgreSQL stack means developer-led teams can extend, self-host, or integrate without fighting legacy architecture.

Object mapping

How PracticeHub objects map to Twenty CRM

Each row shows how a PracticeHub 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.

PracticeHub

Person / Patient

maps to

Twenty CRM

People

1:1
Fully supported

PracticeHub's person/patient records map directly to Twenty's People object. Each record carries name, email, phone, address, and practitioner assignment. In Twenty, the People record links to a Company via the companyId relation. Records without a primary company land as standalone People with no companyId — FlitStack flags these for review before final import.

PracticeHub

Company / Practice Organization

maps to

Twenty CRM

Companies

1:1
Fully supported

PracticeHub organizations or clinic entities map to Twenty's Companies object. Fields like organization name, address, phone, and website transfer directly. If PracticeHub supports parent-child organizational hierarchies, the parent reference maps to Twenty's Company → parentId field. Multi-site organizations in PracticeHub collapse to multiple Company records with their respective addresses.

PracticeHub

Appointment

maps to

Twenty CRM

Custom Activity object (pre-created in Twenty)

1:1
Fully supported

Appointment records have no direct Twenty equivalent — they are not Tasks (which are to-dos) and not Notes. FlitStack creates a custom Activity object in Twenty via Settings → Data Model before import. Fields include appointmentDate, appointmentType, practitionerId, location, status, and duration. Each Activity links to the People record via a relation field.

PracticeHub

Treatment Note

maps to

Twenty CRM

Notes

1:1
Fully supported

Treatment notes from PracticeHub map to Twenty's built-in Notes object. The note body populates the content field. The linked patient/person maps to the Notes → PersonId relation. Created date and modified date are preserved as metadata. If the treatment note is rich-text, Twenty's Note content field handles formatted text.

PracticeHub

Patient Library / Document

maps to

Twenty CRM

Custom Attachment record (pre-created in Twenty)

1:1
Fully supported

Files and documents attached to patient records (diagnostic images, exercise routines, intake forms) have no native equivalent in Twenty's standard objects. FlitStack creates a custom Attachment object with fields for fileName, fileUrl, mimeType, linkedPersonId, and uploadedAt. The fileUrl references the original PracticeHub download URL or a FlitStack-hosted copy if PracticeHub's links expire post-migration.

PracticeHub

Practitioner / Staff Member

maps to

Twenty CRM

Workspace Members

1:1
Fully supported

PracticeHub practitioner and staff records are people records in Twenty's context, but they also need to exist as Workspace Members to own records. FlitStack creates a People record for each practitioner and resolves ownership by matching practitioner email against Twenty Members. If the practitioner has no Twenty account yet, FlitStack invites them before assigning record ownership — no record lands without an owner.

PracticeHub

Custom Compliance Field

maps to

Twenty CRM

Custom Field on People or Activity

1:1
Fully supported

PracticeHub's custom compliance and clinical fields (such as insurance type, referral source, treatment plan status) are not native Twenty fields. Each custom field is pre-created in Twenty's data model (Settings → Data Model) as a text, select, multi-select, or date field matching the source type. The migration plan lists every custom field with its target object and field type before data lands.

PracticeHub

Tag / Label

maps to

Twenty CRM

Custom field (select or multi-select)

1:1
Fully supported

PracticeHub uses tags to classify patients and appointments. Twenty has no native tag object for People, so tags migrate as a multi-select custom field. The exact tag values are mapped one-by-one to the select options in Twenty's data model. Duplicate or synonymous tags are consolidated during the mapping review phase.

PracticeHub

Opportunity / Deal

maps to

Twenty CRM

Opportunities

1:1
Fully supported

If PracticeHub tracks billable services or service agreements as opportunities, those map to Twenty's Opportunities object. Fields include name, amount, stage, expectedCloseDate, and linked CompanyId. Stage values are mapped via pick-list value mapping — your team defines the Twenty stage pipeline structure before migration runs.

PracticeHub

Workflow / Automation

maps to

Twenty CRM

Workflow (must be rebuilt in Twenty)

1:1
Fully supported

PracticeHub workflows, appointment reminders, and automated messaging sequences do not migrate. Twenty's Workflow builder handles day-to-day automations differently. FlitStack exports a JSON description of each PracticeHub workflow logic (trigger, conditions, actions) as a rebuild reference for your Twenty admin. No workflow runs on the new system without deliberate rebuild.

Gotchas + challenges

What specifically takes care here

Platform-specific issues from each side, plus the pair-specific challenges that don't show up on either platform's page on its own.

PracticeHub logo

PracticeHub gotchas

High

1 req/sec API rate limit severely restricts bulk migration speed

Medium

Region-specific API base URLs must be resolved before extraction

Medium

Patient Library assets export as separate binary blobs

Low

Prescription records may reference external Chewy pharmacy integration

Twenty CRM logo

Twenty CRM gotchas

High

Import order is enforced and critical

High

Export limited to 20,000 records and visible columns only

Medium

Soft-deleted records count toward uniqueness and trigger restores

Medium

API rate limits cap at 200 req/min on Organization tier

Low

No native email sequences — follow-up cadences require external tools

Pair-specific challenges

  • PracticeHub's 1 req/sec API rate limit gates extraction speed for large datasets

    PracticeHub enforces a hard rate limit of 1 API request per second per account. This is not a soft throttle — exceeding it returns errors. For a migration involving 50,000 patient records with appointment histories, extraction alone takes approximately 14 hours of API polling before a single record lands in Twenty. FlitStack staggers all requests with 1.05-second intervals to stay compliant. If PracticeHub publishes bulk export endpoints, we use those instead, but the rate limit applies to every HTTP request against the PracticeHub API regardless of endpoint. Teams should plan for extraction windows that run overnight or over weekends for large datasets, and should not schedule the migration cutover assuming the source API can be queried in parallel at high speed.

  • Twenty requires custom fields to be pre-created before CSV import — import does not auto-create fields

    Twenty's CSV import process creates records, not fields. If a column in your import CSV references a field that does not exist in Twenty's data model, the import silently drops that column or errors out depending on the field type. FlitStack generates a complete field pre-creation checklist as part of the migration plan: for each PracticeHub custom property, we specify the target object, field type (text, select, multi-select, date, number, relation), and exact field name to create in Settings → Data Model. We recommend creating all custom fields in Twenty before the first import run. If fields are missing at import time, the import can be re-run after fields are created, but records already imported will not auto-update — a second pass is required.

  • Twenty's import order dependency requires Companies before People before Opportunities

    Twenty's CSV import enforces referential integrity at import time. A People record that references a companyId must have that Company already present in Twenty — otherwise the import rejects the row or sets companyId to null. PracticeHub exports objects individually, so the natural export order from PracticeHub may not match the required import order for Twenty. FlitStack re-structures all CSV exports into the correct sequence: Companies first (with their domain and name fields), then People with resolved companyId references, then Opportunities with their companyId and personId lookups, then custom objects last. If your PracticeHub data has circular references (a person record references a company that itself has no explicit record), we create a placeholder Company or flag for manual resolution before proceeding.

  • Twenty's uniqueness constraint can restore soft-deleted records on import

    Twenty's import process treats email addresses and other unique field values as hard uniqueness constraints. If a record with the same email already exists in Twenty — including records that were soft-deleted and are visible under Command Menu → See deleted records — importing a duplicate will either fail or restore the deleted record depending on the import configuration. This catches teams off guard when migrating from PracticeHub after previous partial migrations or test imports. FlitStack pre-scans both PracticeHub and Twenty for duplicate email addresses before the migration run. Any conflicts are surfaced in the migration plan with a choice: delete the existing Twenty record, merge the data, or skip the PracticeHub record.

  • Healthcare compliance data must be handled as custom fields with restricted access

    PracticeHub stores clinical and compliance data (treatment plans, medical history, referral sources, insurance details) that may constitute Protected Health Information under applicable regulations. Twenty CRM is a general-purpose CRM with no built-in HIPAA compliance model. Clinical fields migrating from PracticeHub land as custom fields on People or custom objects in Twenty, visible to any Twenty user with record access. Before migration, your team must decide which fields to migrate (and under what access controls), which to exclude, and whether a separate compliant storage layer is needed for the most sensitive records. FlitStack migrates the data you specify; access control configuration is a post-migration setup step handled by your Twenty admin.

Migration approach

Six steps for a successful PracticeHub to Twenty CRM data migration

  1. Audit PracticeHub data model and Twenty schema side-by-side

    FlitStack reads PracticeHub's API schema and exports a full object inventory: every object, field, relationship, and custom property with its data type and sample values. We simultaneously document Twenty's current data model via its REST API metadata endpoint. The output is a side-by-side gap analysis that identifies which PracticeHub objects have direct equivalents in Twenty, which require custom objects, which require custom fields, and which have no equivalent and must be rebuilt or archived. This audit runs against a read-only API token scoped to your PracticeHub account.

  2. Pre-create custom fields and objects in Twenty

    Before any data moves, FlitStack generates a field-creation checklist for your Twenty admin: each custom field to create, the target object, the field type, select options (for pick-list fields), and the order to create them. We also create the custom Activity and Attachment objects via Twenty's API using the same field definitions. This step runs in parallel with data extraction and typically takes 1–2 hours once the checklist is approved. Twenty requires an admin-level API token for this step. No import runs until all target fields exist in Twenty's schema.

  3. Resolve practitioners and invite Twenty Members

    Practitioner and staff records from PracticeHub must resolve to Twenty Workspace Members for record ownership to assign correctly. FlitStack extracts all practitioner emails from PracticeHub, checks each against Twenty's Members list (via the REST /users endpoint), and flags any that do not yet exist. We generate a batch invitation list so your team can invite those users before data import. Records assigned to an unmatched practitioner are held with a fallback owner flag — they do not land ownerless. This step prevents the 'orphan records' problem where imported records have no valid owner in Twenty.

  4. Extract PracticeHub data at rate-limited pace and restructure CSVs

    PracticeHub's 1 req/sec rate limit governs extraction. FlitStack paginates through every PracticeHub object (People, Companies, Appointments, Notes, Attachments) with 1.05-second intervals between requests. Each object export is saved as a separate CSV. We then re-structure the CSVs into Twenty's required import order: Companies first, People second (with companyId references resolved), Opportunities third, then custom objects. Any flat multi-table relationships in PracticeHub are denormalized into junction CSV files for import into relation fields. The extraction runs as a background job with checkpointing so interrupted runs resume from the last page.

  5. Run sample migration with field-level diff, then full cutover with delta pickup

    A representative sample (typically 200–500 records spanning all object types) migrates first. FlitStack generates a field-level diff comparing source values in PracticeHub against destination values in Twenty for every mapped field. You review the diff to confirm field mapping accuracy, catch any missing custom fields, and verify practitioner ownership resolution. After sign-off, the full migration runs. A delta-pickup window (24–48 hours) monitors PracticeHub for records created or modified during the cutover window, capturing in-flight changes. The audit log records every imported record with its source ID for traceability. One-click rollback is available if reconciliation reveals missing data beyond agreed tolerances.

Platform deep dives

Context on both ends of the pair

PracticeHub logo

PracticeHub

Source

Strengths

  • No setup fees and no minimum contract terms reduce upfront commitment for small practices.
  • Multi-region API infrastructure supports UK (Neptune/London) and ANZ (Sydney) deployments with region-specific base URLs.
  • Patient mobile app handles appointment management, reminders, check-in, and payments as a bundled feature.
  • Built-in policy and compliance management reduces third-party tooling for accreditation workflows.
  • Publicly documented migration guide for Cliniko switchers signals active competitive positioning.

Weaknesses

  • API rate limit of 1 request per second is extremely restrictive for bulk data migration of large patient bases.
  • No publicly documented bulk export endpoint; all extraction relies on paginated REST API calls.
  • Limited pricing transparency with no self-serve pricing page found in research.
  • Patient Library binary assets (images, documents) may require separate handling from structured record exports.
  • Region-based URL architecture requires account-domain and region identification before any API calls can be made.
Twenty CRM logo

Twenty CRM

Destination

Strengths

  • AGPL-3.0 open-source license with full source code on GitHub — no vendor lock-in, no sunset risk.
  • Unlimited users and unlimited custom objects on self-hosted, with no feature gating based on headcount.
  • REST and GraphQL APIs available on all paid tiers, not locked behind an enterprise add-on fee.
  • MCP server and webhooks shipped as standard features, not premium upgrades.
  • Modern PostgreSQL-backed data model that developer teams can query, extend, and self-host.

Weaknesses

  • Recent v1.0 release means limited production hardening compared to CRMs with multi-year operational track records.
  • No native email sequencing or sales engagement tools — follow-up cadences require a separate platform.
  • No native two-way email sync or inbox integration, requiring third-party connectors for full activity logging.
  • Self-hosting 'free' pricing hides real infrastructure and DevOps costs that stack up over time.
  • Workflow automation is functional but lacks the complexity needed for sophisticated multi-step sales motions.

Complexity grading

How hard is this migration?

Standard CRM migration. 2 of 8 objects need a mapping; the rest are 1:1.

B

Overall complexity

Standard migration

Derived from compatibility, mapping clarity, API constraints, and data volume across PracticeHub and Twenty CRM.

  • Object compatibility

    B

    2 of 8 objects need a mapping; the rest are 1:1.

  • Field mapping clarity

    C

    Field mapping is derived from defaults — final spec confirmed during the sample migration.

  • Timeline complexity

    B

    8-object category — typical timelines run 2–7 days end-to-end.

  • API constraints

    B

    PracticeHub: 1 request per second per account.

  • Data volume sensitivity

    B

    PracticeHub doesn't expose a bulk API — REST + parallelization used for high-volume runs.

Estimator

Estimate your PracticeHub to Twenty CRM migration cost

Rule-based pricing — no per-record fees, no manual quotes. Migrations over 2M records are scoped individually.

Step 1

What are you migrating?

Pick a category, then your source and destination platforms.

Category

FAQ

Frequently asked questions about PracticeHub to Twenty CRM data migrations

Answers to the questions buyers ask most during PracticeHub to Twenty CRM migration scoping. Not seeing yours? Book a call.

Can't find your answer?

Walk through your PracticeHub to Twenty CRM migration with a real engineer — 30 minutes, free, written quote within 24 hours.

Book a free 30 minute consultation

For under 50,000 total records, most PracticeHub-to-Twenty migrations complete in 48–72 hours of clock time. The dominant variable is PracticeHub's API rate limit of 1 request per second — extracting 50,000 records takes approximately 14 hours of API polling alone. Larger datasets over 200,000 records extend to 10–14 days when accounting for rate-limited extraction, custom field pre-creation, and multi-batch import sequencing. The planning and schema review phase adds 3–5 days before extraction begins.

Adjacent paths

Related migrations to explore

Ready when you are

Move from PracticeHub.
Land in Twenty CRM, intact.

Tell us record counts and timeline. We'll come back with a written quote inside 1 business day — no commitment, no sales pitch.

Accuracy guarantee Rollback included Quote in 1 business day