What we touch, and what we keep.

A migration reads your entire customer history out of one system and writes it into another. That is worth a page of specifics rather than a badge, so here are the mechanisms, the subprocessors, and the disclosure most tools leave out.

0
records sent to a model
6
subprocessors, all named
3
things that never leave

How your data is held

OAuth, not pasted credentials

Attio, HubSpot, Pipedrive and Salesforce all connect over OAuth with scoped, revocable tokens — revoke us from your own admin and we are out, no ticket required. Affinity has no OAuth, so it takes an API key, and an Attio API key is offered only as a clearly-marked fallback.

Tokens encrypted with a key we do not store beside them

Every credential is sealed under its own data key, which is itself wrapped by a master key held outside the database. One module in the codebase can decrypt, and one table holds token material. A database dump on its own opens nothing.

Background jobs carry an id and nothing else

The durable job that runs your migration receives a single migration id. Credentials and records are fetched inside the job, from encrypted storage, and never travel through a queue payload, a log line or a dashboard. Secrets and personal data are never logged at all.

Every request re-checks who owns the row

Ownership is enforced at the data layer on each request rather than in the page that renders it, and a migration belonging to someone else answers the same way one that does not exist does — so an id cannot be probed for.

Your CSV is deleted when the job finishes

Uploaded files are removed on finalize. What we keep is the structure you approved, the field mapping, the id map and the provenance ledger — the bookkeeping that makes a re-run idempotent and a rollback complete. Not your rows.

Reconnecting to a different Attio workspace stops the run

Every id we hold is scoped to one workspace. If the connected workspace changes, resume, retry, full-run and rollback are all refused at the door rather than writing this migration's records into somebody else's Attio.

What reaches Claude, exactly

Shuttio uses a model to propose your Attio structure. That is the only place one is involved, and this is the whole of what it receives.

What the model sees

Your answers to the intake questions, and your source system's schema: object names, field names and types, and at most three sample values per field, each truncated to 80 characters. That sample is what lets it tell a pipeline stage from a free-text note.

What the model never sees

The import itself. The structure engine never writes to Attio and the Attio writer never calls a model — they are separate paths on purpose. Your records stream from your CRM into Attio without passing through Claude, whether you are moving fifty rows or five million.

What the model can decide

Nothing, on its own. It proposes a structure and a field mapping; a strict validator rejects anything malformed before you ever see it; and you edit and approve both before a single write reaches Attio.

Three things that are never migrated anywhere

For any reason, on any plan, at any record count.

Your record rows

Never leaves

The structure engine and the Attio writer are separate paths. Records stream from your CRM into Attio without passing through a model.

Your uploaded CSV

Never leaves

Deleted on job finalize. What we keep is the structure, the mapping, the id map and the provenance ledger — not your rows.

Credentials

Never leaves

Sealed under a per-record data key wrapped by a master key held outside the database, and never placed in a job payload, a log line or a dashboard.

Who else processes it

The full list. Shuttio is operated by Venturise OÜ in Tallinn, Estonia.

NeonPostgres database
VercelApplication hosting
InngestDurable job execution — receives migration ids only
AnthropicClaude, for the structure proposal described above
GoogleSign-in only, via OAuth
ResendCompletion emails, when enabled

Getting back to where you were

Cancelling a migration deletes every record, note, task, meeting, list entry, attribute and select option that migration created, in reverse order, working from a ledger written as each one was made. Anything that was in your workspace beforehand is never touched.

Two things a rollback leaves in place are the custom objects and lists it created: Attio's API cannot delete a list, and deleting an object would take every record in it along, including any added since. Both are listed for you by name at the end of a rollback rather than quietly left behind, so the cleanup is a few clicks in Attio settings and not a discovery six months later.

Read it, forward it, then start with fifty records.

Free at any record count. Nothing is written to Attio until you have approved the structure and the field mapping.