CRM migration

Migrate from Cliniko to Twenty CRM

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

Cliniko logo

Cliniko

Source

Twenty CRM

Destination

Twenty CRM logo

Compatibility

86%

12 of 14

objects map 1:1 between Cliniko and Twenty CRM.

Complexity

BStandard

Timeline

5–7 days

Rollback included Accuracy guarantee Field-level validation

Overview

What this migration involves

Cliniko organizes healthcare data around patients, practitioners, appointments, and treatment notes. Twenty CRM uses a standard B2B CRM object model: People, Companies, Opportunities, Tasks, and Notes. These models diverge significantly — Cliniko's patient record carries clinical data (DOB, insurance, concession cards) and appointment history, while Twenty's People object is designed for contacts in a sales context. FlitStack AI resolves this by mapping Cliniko patients to Twenty People, appointments to Tasks, treatment notes to Notes, and invoices to a custom Invoice object. We use Cliniko's built-in CSV export (Settings → Data exports) and bulk-import into Twenty via its API and CSV import, respecting Twenty's required import order: Companies first, then People, then Opportunities, then custom objects. Practitioners export from Cliniko and land in Twenty as WorkspaceMembers resolved by email match before appointments can link to them. What does not migrate: appointment reminder automations, SMS credits, Telehealth session logs, and Cliniko's billing model — those require separate decisions post-migration. We deliver a field-level diff on a sample slice before committing the full run.

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

Cliniko logo

Cliniko

What's pushing teams away

  • API access is tied to individual user permissions, meaning API keys inherit role-based access controls — a practitioner-key may not expose all records a migration requires, complicating bulk export scoping.
  • Cliniko's automation capabilities (e.g. appointment reminders, form-triggered updates) do not export; they must be manually rebuilt in the destination platform, increasing migration effort for workflow-heavy practices.
  • Large data exports generate in the background and can take considerable time during busy hours, which may delay migration cutover timelines for practices with high appointment volumes.
  • The platform lacks a native HubSpot or Salesforce CRM-style pipeline view for tracking patient leads or referral sources — practices that outgrow Cliniko often cite the need for a dedicated CRM layer.

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 Cliniko objects map to Twenty CRM

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

Cliniko

Patient

maps to

Twenty CRM

People

1:1
Fully supported

Cliniko's patient maps directly to Twenty's People object. We map firstname, lastname, email, phone, date_of_birth, and address fields. Cliniko-created and Cliniko-updated timestamps are preserved as custom datetime fields since Twenty's native timestamps reflect migration time. Cliniko's patient ID is stored as Source_System_ID__c for delta-run de-duplication.

Cliniko

Patient Address

maps to

Twenty CRM

People (address fields)

many:1
Fully supported

Cliniko stores addresses as a separate object linked to patients with address types (e.g., 'Street', 'Postal'). Twenty People has a single address field. We take the Cliniko address with type 'Street' (or the first address) and populate Twenty's address field as a single formatted string. Additional address types are stored as custom text fields (e.g., Mailing_Address_2__c) for reference.

Cliniko

Appointment

maps to

Twenty CRM

Task

1:1
Fully supported

Cliniko appointments do not map 1:1 to any Twenty object — Twenty has no appointment entity. We transform appointments to Tasks: the Cliniko appointment date and time become the Task due date and start datetime; the end time becomes the Task end datetime. The Cliniko appointment status ('Awaiting', 'Arrived', 'In Progress', 'Completed', 'No Show') is mapped to a custom Cliniko_Appointment_Status__c field since Twenty Task status has fewer values.

Cliniko

Appointment (appointment_type)

maps to

Twenty CRM

AppointmentType (custom object)

1:1
Fully supported

Cliniko appointment types (e.g., 'Initial Consultation', 'Follow-up', 'Massage 60min') have no equivalent in Twenty's standard objects. We create a custom object 'AppointmentType' in Twenty with name and duration fields, then link appointments to it via a relation field. If you prefer a flat structure, appointment types can also become a custom pick-list field on the Task.

Cliniko

Practitioner

maps to

Twenty CRM

WorkspaceMember

1:1
Fully supported

Cliniko practitioners are staff members who create appointments and treatment notes. They map to Twenty WorkspaceMembers resolved by email match. We import practitioners first (before appointments and notes) so their Twenty IDs exist for relation resolution. Practitioners without a matching email in Twenty are flagged before migration and assigned to a fallback WorkspaceMember.

Cliniko

Treatment Note

maps to

Twenty CRM

Note

1:1
Fully supported

Cliniko treatment notes (customizable SOAP-format templates per clinic) migrate as Twenty Notes. The note body content maps to Note.body; the Cliniko treatment note ID is stored as Source_System_ID__c. Note.body is plain text — rich formatting from Cliniko templates is preserved as plain text, and template field labels are included in the body for context.

Cliniko

Invoice

maps to

Twenty CRM

Invoice (custom object)

1:1
Fully supported

Cliniko invoices have no equivalent in Twenty's standard object model. We create a custom object 'Invoice' in Twenty with fields for invoice number, total amount, outstanding amount, status, and dates. Invoice status from Cliniko ('Draft', 'Sent', 'Paid', 'Void') maps to a custom pick-list; 'Paid' and 'Void' states are preserved as custom values.

Cliniko

Invoice Line Item

maps to

Twenty CRM

Invoice Line Item (custom object) or Invoice custom fields

1:many
Fully supported

Cliniko invoice line items link products or services to invoices. For simple cases, we store the product name and quantity as custom fields on the Invoice object. For complex invoices with multiple line items, we create a custom object 'InvoiceLineItem' linked to Invoice with product name, quantity, unit price, and total.

Cliniko

Payment

maps to

Twenty CRM

Payment (custom object)

1:1
Fully supported

Cliniko payments received against invoices have no native equivalent in Twenty. We create a custom object 'Payment' with fields for payment ID, amount, date, and a relation to the corresponding Cliniko-generated Invoice (stored as Source_System_ID__c). Payment status (fully paid, partially paid, refunded) is preserved as a custom field.

Cliniko

Product / Service

maps to

Twenty CRM

Product (custom object)

1:1
Fully supported

Cliniko products and services (used in appointments and invoices) do not have a native equivalent in Twenty. We create a custom object 'Product' with name, description, and unit price fields. Products linked to appointments via the appointment type are also stored as a custom field on the AppointmentType object for traceability.

Cliniko

Patient Insurance Profile

maps to

Twenty CRM

People (custom fields)

1:1
Fully supported

Cliniko stores insurance provider, member ID, policy number, and concession card details on patient records. Twenty has no native insurance fields. We map these as custom text fields on the People record: Insurance_Provider__c, Insurance_Member_ID__c, Policy_Number__c, Concession_Type__c. This data is preserved for reference but requires manual entry for new patients post-migration.

Cliniko

Patient Custom Fields

maps to

Twenty CRM

People (custom fields)

1:1
Fully supported

Cliniko clinics commonly add custom fields to patient records for clinic-specific data (e.g., 'Preferred Contact Method', 'Emergency Contact', 'Referral Source'). Each Cliniko custom field becomes a Twenty custom field with the same name and field type, created in Settings → Data Model before import. Field values are mapped value-by-value during the migration run.

Cliniko

Appointment Custom Fields

maps to

Twenty CRM

Task (custom fields)

1:1
Fully supported

Some Cliniko setups add custom fields to appointments (e.g., 'Room Number', 'Equipment Used'). These map to custom fields on the Task object in Twenty, created before import. Note that custom fields on appointments in Cliniko are stored in a separate export and must be joined to the main appointment export by record ID during mapping.

Cliniko

SMS Credit / Telehealth Fee

maps to

Twenty CRM

No equivalent

1:1
Fully supported

Cliniko bundles SMS credits and Telehealth session fees into its subscription billing. Twenty CRM has no equivalent billing or communications-credit model. These records do not migrate. If SMS appointment reminders are in use, they must be replaced with Twenty workflow-based reminders or a third-party SMS integration post-migration.

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.

Cliniko logo

Cliniko gotchas

Medium

Background export generation delays for large datasets

Medium

Charts export is separate from the main data panel

High

API key permissions gate record visibility

Medium

Form template configurations do not export

Low

The old Appointments export has been deprecated

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

  • Appointment status values collapse into a custom field

    Cliniko tracks appointment statuses with five values: Awaiting, Arrived, In Progress, Completed, and No Show. Twenty's Task status field has only three values: Not Started, In Progress, and Completed. The richer Cliniko statuses cannot map directly to Twenty's Task status field without data loss. We handle this by creating a custom pick-list field (Cliniko_Appointment_Status__c) on the Task object and storing the original Cliniko status value there. If you need to report on 'Arrived' vs 'Awaiting' rates in Twenty, you query the custom field — not the native Task status. This is a pair-level gotcha because it applies specifically to Cliniko-to-Twenty migrations and requires custom field creation before data lands.

  • Import sequence dependency — practitioners must land before appointments and notes

    Twenty's import system enforces referential integrity: the 'one' side of a relationship must exist before the 'many' side can reference it. This means practitioners (WorkspaceMembers) must be imported and accepted in Twenty before appointments and treatment notes can link to them. Cliniko exports practitioners and appointments as separate files. If you attempt to import appointments before practitioners are live in Twenty, the assigneeId and authorId relations will fail. We sequence the migration so practitioners import first, we wait for acceptance, then import appointments and treatment notes. This adds a planning step that teams migrating between other platforms do not encounter.

  • Treatment notes collapse from structured templates to plain text

    Cliniko treatment notes support customizable templates with named fields (e.g., Subjective, Objective, Assessment, Plan — the SOAP format). When these migrate to Twenty Notes, the template structure is lost: all content lands in a single Note.body text field. Template field labels become part of the text rather than structured fields. For clinics that use treatment note templates for compliance or audit purposes, this structural loss is significant. We include all template field names and values in the note body for readability, but any reporting or filtering you do on structured SOAP fields in Cliniko must be rebuilt as custom fields or filters on Note.body in Twenty.

  • Insurance and concession data maps to untyped custom text fields

    Cliniko stores insurance provider name, member ID, policy number, and concession card type directly on patient records. Twenty has no native insurance, policy, or concession fields. We map these to custom text fields on the People object (Insurance_Provider__c, Insurance_Member_ID__c, Policy_Number__c, Concession_Type__c). Text fields do not enforce data types, so member ID formats vary. If your clinic relies on insurance fields for eligibility checks or claim preparation in Cliniko, the custom text fields in Twenty serve as a reference record only — they do not replicate the validation or workflow logic Cliniko provides around those fields.

  • SMS credits and Telehealth fees have no destination equivalent

    Cliniko bundles SMS credit tracking and Telehealth session fees into its subscription model. SMS credits are tracked as a usage metric with per-message billing; Telehealth sessions generate line items on invoices. Twenty CRM has no native SMS credit tracking, no Telehealth session object, and no concept of communication credits. We do not migrate SMS credit balances or Telehealth session logs. If your clinic uses Cliniko's built-in SMS appointment reminders, those automations do not transfer. They must be rebuilt using Twenty's Workflows feature or a third-party SMS integration. This gotcha is Cliniko-to-Twenty specific because other CRMs (HubSpot, Salesforce) also lack healthcare billing primitives, but the specific SMS-credit model is unique to Cliniko.

Migration approach

Six steps for a successful Cliniko to Twenty CRM data migration

  1. Audit Cliniko data and identify the full export scope

    FlitStack AI begins every Cliniko migration by reviewing the full export scope. We pull the patient list, appointment export, treatment notes, invoices, payments, products, and any custom-field exports from Cliniko's Settings → Data exports. We identify custom fields on patient records and appointment types from the export column headers, note address records and insurance profiles, and count record volumes per object. This audit produces the migration scope document: which objects map directly, which require custom objects in Twenty, and which records have no CRM equivalent.

  2. Set up Twenty workspace: data model, custom objects, and user provisioning

    Before any data moves, FlitStack AI configures Twenty's data model to receive Cliniko data. We create the custom Invoice and Payment objects with all required fields, add the custom AppointmentType object, and create any custom fields needed on the People and Task objects (insurance fields, appointment status, original timestamps). We also create the custom fields for appointment-type relations and Practitioner Source_System_ID__c on WorkspaceMembers. Your team must invite all practitioners to Twenty and have them accept invitations before we import appointments and notes — their Twenty user IDs are required for relation resolution.

  3. Import in Twenty's required order: Companies, then People, then Tasks, then Notes

    Following Twenty's import sequencing rules, FlitStack AI imports Companies first (if any organizational records exist in Cliniko), then People with all custom fields and address merges applied. Next, we import the AppointmentType custom object so Twenty IDs exist for the appointment-type relation. Then we import appointments as Tasks — mapping dates, practitioner links, and the Cliniko appointment status to the custom field. Treatment notes follow as Notes objects linked to the patient People record. Invoice and Payment custom objects are imported last. We validate foreign-key integrity at each stage.

  4. Run a sample migration with field-level diff on a representative slice

    A representative slice migrates first: typically 100–500 patient records spanning multiple practitioners, 200–500 appointments across several types and statuses, 50–100 treatment notes, and 20–50 invoices and payments. We generate a field-level diff showing source values and destination values for every mapped field. You can verify that appointment statuses landed in the custom field, practitioner links resolved correctly, insurance fields populated, and invoice amounts match. This step surfaces any field-level mapping errors before the full run commits.

  5. Execute full migration with delta pickup and rollback readiness

    The full migration runs against Twenty using Cliniko's complete export. A delta-pickup window (24–48 hours after the initial load) captures any Cliniko records created or modified during the cutover window. Audit logs capture every record operation with before and after snapshots. One-click rollback is available if reconciliation fails. After rollback, any in-flight changes in Cliniko that occurred during the window are re-captured and re-loaded. Your team continues working in Cliniko throughout — FlitStack AI uses export files only, with no disruption to active appointments or patient records.

  6. Deliver migration report, custom object documentation, and rebuild reference

    After go-live, FlitStack AI delivers a complete migration report: record counts per object, error log, and a field-mapping reference document showing every Cliniko field and its Twenty destination. For items that require manual action post-migration — SMS reminder automations, Telehealth workflow rebuilds, insurance field validation setup — we provide a rebuild reference guide. The Cliniko workflow definitions are exported as a JSON reference file so your Twenty admin can reconstruct appointment-reminder automations in Twenty Workflows.

Platform deep dives

Context on both ends of the pair

Cliniko logo

Cliniko

Source

Strengths

  • Single flat-rate plan with unlimited patients, users, locations, and storage — no per-seat or per-record throttling.
  • Built-in invoicing, appointment scheduling, treatment notes, and reporting in one cloud-hosted application.
  • Telehealth included at no extra cost, launched and maintained without a paywall.
  • Admin-accessible data export panel covering appointments, patients, invoices, transactions, and more.
  • REST API with HTTPS enforcement, JSON responses, and a published OpenAPI schema for programmatic access.

Weaknesses

  • API keys inherit the role-based permissions of the user they belong to, so a read-only or practitioner-level key may not expose all records needed for a full migration export.
  • Form template builders (the configuration for patient intake forms) are not exported via the data panel and must be recreated manually in the destination.
  • The old Appointments export is deprecated; the replacement Reports-based export has different column layouts that require mapping adjustments during migration scoping.
  • Background export generation for large datasets can be slow during busy hours, with no real-time progress API — only email notification on completion.
  • No native automation export; appointment reminders, form-triggered patient field updates, and similar rules must be manually rebuilt in the destination system.
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. 1 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 Cliniko and Twenty CRM.

  • Object compatibility

    B

    1 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

    Cliniko: Not publicly documented in the OpenAPI schema or public help docs.

  • Data volume sensitivity

    B

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

Estimator

Estimate your Cliniko 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 Cliniko to Twenty CRM data migrations

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

Can't find your answer?

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

Book a free 30 minute consultation

Most Cliniko-to-Twenty migrations complete in 5–7 days of clock time for under 50,000 total records. The planning and schema-setup phase takes 1–2 days; the sample migration with field-level diff takes 1 day; the full migration run takes 1 day; and the delta-pickup window runs 24–48 hours after cutover. Larger setups with 50,000–200,000 records or complex appointment histories extend to 2–3 weeks, particularly if custom objects and custom-field creation require extended validation.

Adjacent paths

Related migrations to explore

Ready when you are

Move from Cliniko.
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