Migrate from Attio to Relm in one agent run
Export your Attio CSVs, hand them to an AI agent along with a Relm API key, and the agent does the rest: recreates your pipeline, registers your custom attributes as fields, and batch-loads every person, company, deal and note. No manual re-entry, no import wizard.
This guide walks through the whole move: what to export from Attio, how each Attio object and attribute maps onto Relm, the exact API calls an agent makes, and how to verify the result before you switch over. Everything here works over plain REST, but the intended path is simpler - you paste a prompt into Claude or any MCP client and supervise.
Why teams move from Attio to Relm
Attio deserves its reputation. Its data model - objects with typed attributes, records, lists with list-specific attributes - is genuinely flexible, and the workspace UI is one of the best in the category. If humans are the ones working your CRM every day, Attio is a strong choice, and nothing in this guide argues otherwise.
The reason to move is a change in who operates the CRM. Attio is built around a human workspace: views, lists, collaborative notes, per-seat pricing. Relm inverts that. The REST API and the native MCP server are the product, and the dashboard is a thin layer on top. The practical differences for an agent-driven setup:
- MCP-native. Relm ships a first-party MCP server at
https://api.relmcrm.com/mcp. Every CRM operation is a typed tool; an agent connects with one bearer key and needs no glue code. - Self-describing.
GET /v1/schemareturns every object, field and enum value in your workspace, so the model reads the contract at runtime instead of guessing. - Self-correcting errors. Failures come back as RFC-9457 problem+JSON with
valid_optionsandsuggestion, so an agent fixes its own call on the next turn. - Usage pricing, not seats. Attio charges per user per month. Relm charges per API request - Free is 1,000 requests a month with no card, Pro is $29/mo for 100,000, Scale is $249/mo for 2,000,000. Ten agents and two humans cost the same as one of each.
- A free rehearsal environment. A
relm_test_key writes to an isolated dataset that is free, unlimited, and invisible to live data - so you can run the whole migration twice: once to check it, once for real.
Step 1: export your data from Attio
Attio exports CSV per object. Open a view of People, then Companies, then Deals, and use the view's export option to download each as a CSV - columns are named after your attributes, including any custom ones. If your deals live on a list (the common Attio pattern, with a status attribute for stage), export from the list view so the stage and any list-specific attributes ride along.
Two things do not travel in record CSVs: notes and tasks. If the history matters, pull them from Attio's REST API (GET /v2/notes and GET /v2/tasks on api.attio.com) into a JSON or CSV file. Each note carries the record it is attached to and a created timestamp - both survive the move, as you will see below.
Step 2: the field mapping
Relm's model is deliberately small: contacts, companies, deals and activities, plus custom fields for everything else. Attio's standard attributes map cleanly; custom attributes become Relm custom fields, registered once and typed.
| Attio | Relm | Notes |
|---|---|---|
| Company → Name | company.name | Required. |
| Company → Domains | company.domain | Attio allows several; take the primary one. |
| Company → Description, Categories, Employee range | company.custom_fields.* | Register via POST /v1/fields. |
| Person → Name | contact.first_name / last_name | Split on the first space if exported as one column. |
| Person → Email addresses | contact.email | Primary address; email is optional in Relm, so email-less people still import. |
| Person → Phone numbers | contact.phone | |
| Person → LinkedIn | contact.linkedin_url | |
| Person → Job title | contact.custom_fields.job_title | Custom text field. |
| Person → Company | contact.company_id | Resolve by the company's domain after companies are loaded. |
| Deal → Name | deal.title | Required. |
| Deal → Value | deal.value_cents + currency | Integer minor units: $12,000 becomes 1200000. |
| Deal → Stage (list status) | deal.stage in a mirrored pipeline | Stages recreated 1:1, see below. |
| Deal → Associated company / people | deal.company_id / primary_contact_id | |
| Deal → Owner | deal.custom_fields.owner | Custom text field. |
| Note / Task (via Attio API) | activity with occurred_at | Type note; the original timestamp is preserved. |
Step 3: one-time setup
Before loading records, the agent makes a handful of idempotent setup calls: a pipeline whose stages are exactly your Attio stages, and one field registration per custom attribute. Attio's default deal stages are Lead, In Progress, Won and Lost - if you customized them, map yours 1:1 instead.
# mirror the Attio deal stages as a Relm pipeline
curl -X POST https://api.relmcrm.com/v1/pipelines \
-H "Authorization: Bearer relm_test_..." \
-H "Content-Type: application/json" \
-d '{"name":"Sales","stages":["lead","in_progress","won","lost"]}'
# register custom fields once, then send values under custom_fields
curl -X POST https://api.relmcrm.com/v1/fields \
-H "Authorization: Bearer relm_test_..." \
-H "Content-Type: application/json" \
-d '{"object":"contact","key":"job_title","data_type":"text"}'
Note the relm_test_ key: rehearse the entire import in test mode first. It is free, does not count against any quota, and the data never touches your live workspace.
Step 4: load in batches of 100
POST /v1/batch takes up to 100 operations per call and returns a per-operation result array - one bad row does not fail the batch. Records get server-assigned IDs, so load in dependency order across batches: companies first, then contacts referencing company IDs, then deals, then activities. Within a single batch, operations cannot reference each other's new IDs - the cmp_ and deal_ IDs in the example below came from earlier batches. Each operation counts against your monthly quota exactly like an individual request - batching saves round-trips, not quota.
curl -X POST https://api.relmcrm.com/v1/batch \
-H "Authorization: Bearer relm_test_..." \
-H "Content-Type: application/json" \
-d '{"operations":[
{"object":"contact","data":{
"first_name":"Maya","last_name":"Chen",
"email":"[email protected]",
"linkedin_url":"https://linkedin.com/in/mayachen",
"company_id":"cmp_9f2k1x7q",
"custom_fields":{"job_title":"Head of Operations"}}},
{"object":"deal","data":{
"title":"Northwind Labs - annual",
"pipeline":"sales","stage":"in_progress",
"value_cents":1200000,"currency":"USD",
"company_id":"cmp_9f2k1x7q"}},
{"object":"activity","data":{
"type":"note","body":"Intro call went well; wants Q3 rollout.",
"deal_id":"deal_7h3m2v8s",
"occurred_at":"2025-11-14T09:30:00Z"}}
]}'
{ "object": "batch", "count": 3, "succeeded": 3, "failed": 0, "results": [...] }
The occurred_at on that note is doing real work: it backdates the activity to when it actually happened in Attio, so your timeline survives the move instead of collapsing into one import day.
Or skip the curl: hand it to your agent
The path most people take. Point any MCP client - Claude, Cursor, anything that speaks the protocol - at https://api.relmcrm.com/mcp with your key (setup details in the docs and the agent hub), attach the Attio CSVs, and say:
Import my Attio workspace into Relm from the attached CSVs
(people.csv, companies.csv, deals.csv, notes.json).
1. Call relm_describe_schema first.
2. Create a pipeline named "Sales" whose stages match the Stage
column in deals.csv, in order.
3. Register custom fields for any column that is not a standard
Relm field (job_title, owner, employee_range).
4. Load with relm_batch, 100 ops per call, in dependency order:
companies, then people, then deals, then notes as activities
with occurred_at set to each note's created date.
5. Skip nothing - people without an email are fine.
6. Report counts per object when done, and every failed row.
The agent discovers the whole contract from relm_describe_schema, and it self-corrects as it goes: an unknown stage or field comes back as a 422 with valid_options and the exact call to create it. This is the same read-the-schema-then-act loop described in what is a CRM for LLMs - migration is just its largest single workout.
Step 5: verify before you switch
Do not trust "done", verify it. Three checks, all cheap:
- Counts. Page each list endpoint (
GET /v1/contacts?limit=100, then follownext_cursor) and compare totals against the row counts of your Attio CSVs. Your agent can do this in one prompt: "count every object and compare to the source files." - Spot-checks. The list endpoints take a
qsubstring filter -GET /v1/contacts?q=chenmatches on email, first and last name, phone and LinkedIn;/v1/companies?q=northwindmatches name and domain;/v1/deals?q=annualmatches title. Pick ten records you know well and confirm fields, stage and linked company survived intact. - Re-run safety. Contacts are safe to replay: a duplicate email returns a 409 conflict carrying the existing record, so re-imported people converge instead of duplicating. Companies, deals and activities have no server-side dedupe - if a batch partly fails, re-run only the failed rows, which the per-operation results identify exactly. (An
Idempotency-Keyheader guards single-record POSTs against network retries;POST /v1/batchdoes not take one.)
When the test-mode run checks out, repeat the exact same run with your relm_live_ key. One practical note on quota: the Free plan's 1,000 requests a month will cover a small workspace, but a real import belongs on Pro - each batch operation is one request, so 5,000 records plus verification fits well inside Pro's 100,000. On paid plans you can also set a hard spend cap so an oversized import stops cleanly instead of running up overage.
After the move
Migration is the entry point, not the destination. Once the data is in Relm, the interesting part starts: your agent works the CRM directly - logging calls, advancing deals, running follow-ups - over the same API it used for the import. How to give your AI agent a CRM covers that operating loop, and the API docs hold the full reference for every endpoint used above.
FAQ
How long does an Attio to Relm migration take?
For a typical workspace of a few hundred to a few thousand records, one agent run of a few minutes. POST /v1/batch accepts up to 100 operations per call with per-op results, so a 2,000-record workspace is about 20 batch calls plus one-time setup for the pipeline and custom fields.
Do I need to write code to migrate from Attio?
No. Export CSVs from Attio, then give any MCP client - Claude, ChatGPT, Cursor - the files plus a Relm API key pointed at https://api.relmcrm.com/mcp. The agent reads the live schema with relm_describe_schema, registers custom fields, creates the pipeline, and loads everything with relm_batch. The curl examples in this guide are for people who prefer scripts.
What happens to my Attio deal stages?
They are recreated 1:1. One call to POST /v1/pipelines creates a named pipeline whose ordered stages are exactly your Attio stages - for example lead, in_progress, won, lost - and every imported deal is placed in the stage it held in Attio.
What about custom attributes I created in Attio?
Register each one once with POST /v1/fields (object, key, data_type), then send values under custom_fields on every record. Types are enforced - a number field rejects text - so bad rows surface during the import instead of later.
Will re-running the import create duplicates?
For contacts, no - creating a contact with an email that already exists returns a 409 conflict that includes the existing record, so re-imported people are caught. Companies, deals and activities have no server-side dedupe, so do not blindly replay those batches - re-run only the rows that failed, which each batch's per-operation results identify exactly. An Idempotency-Key header protects single-record POSTs against network retries; POST /v1/batch does not take one.
How much does the migration cost?
Rehearsing in test mode (relm_test_ key) is free and unlimited. On live keys every batch operation counts as one request: the Free plan includes 1,000 requests a month with no card, Pro is $29/mo for 100,000, Scale is $249/mo for 2,000,000. A 5,000-record import fits comfortably in Pro's first month.
Ready to move?
Mint a free test key, hand your agent the CSVs, and rehearse the whole migration today. See pricing.
Start free →