Skip to content

How to Export Data from Attio: API Limits, CSV, and Portability

Learn every method to export data from Attio — CSV views, workspace backups, and the REST API — plus real rate limits, enriched data restrictions, and migration trade-offs.

Roopendra Talekar Roopendra Talekar · · 15 min read
How to Export Data from Attio: API Limits, CSV, and Portability
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

How to Export Data from Attio: API Limits, CSV, and Portability

Attio gives you three ways to get data out: native CSV/Excel export from any view, a full workspace backup (admin-only, zipped CSVs), and the REST API for programmatic extraction at up to 100 read requests per second. Each method has blind spots — most notably, enriched data cannot be exported through any of them — so picking the right approach depends on what you need, how much of it, and whether it contains enriched attributes.

This guide covers each extraction method in detail, documents the real API constraints, and flags the edge cases encountered across large-scale CRM migrations.

Which export method should you use?

Use this decision tree before reading further:

Is this a one-time export?
├── Yes → Do you need enriched attribute values?
│   ├── Yes → Use API (read enriched fields → write to custom attributes → export CSV)
│   └── No → Under 10,000 records per object?
│       ├── Yes → CSV export from view (fastest)
│       └── No → API with pagination (avoids view column limits and row truncation)
└── No (recurring) → Do you need relationship IDs preserved?
    ├── Yes → Custom API script or Flatly to cloud storage
    └── No → Coefficient (scheduled Google Sheets refresh) or Zapier/Make

If you're doing a full migration to another CRM, always use the API. CSV exports flatten relationships into column values and drop enriched fields. The API preserves linked record IDs, which is what you need to reconstruct the relationship graph in a target system.

What data can you export from Attio?

Attio's exportable data includes records (Companies, People, Deals, Users, Workspaces), custom objects, list entries, notes, tasks, comments, files, and attribute configurations. Attio is a relationship-intelligence CRM built around records, lists, and attributes, with a highly flexible data model where you define the objects and attributes that matter to your team.

What you cannot export is equally important:

  • It is not possible to export enriched data from Attio. If you overwrite Attio's enriched data manually, data that you have entered yourself is able to be exported. If a view includes enriched attributes, those cells will be blank in the exported file.
  • Emails synced into Attio cannot be exported at all — not through the UI and not through the workspace backup.
  • Meetings and call recordings are excluded from the workspace export but can be pulled via dedicated API endpoints.

This enriched-data limitation is the single biggest surprise for teams planning a migration off Attio. Enriched attributes — things like auto-populated company descriptions, employee counts, and social handles sourced by Attio — render as blank cells in every CSV export. This is a licensing constraint, not a technical bug: Attio's enrichment data is sourced and maintained by Attio under third-party data agreements, and they contractually cannot allow it to leave the platform.

How to export a view or list as CSV

You can export any table or kanban view in Attio as a CSV or Excel file. Every column visible in your table view will become a column in the exported file. For kanban views, the attributes shown on each card are exported instead.

Steps

  1. Navigate to the object or list you want to export (e.g., Companies, People, a custom object, or any list).
  2. Make sure your table view includes columns for all the attributes you want to export. If you're exporting a kanban view, ensure the cards show the attributes you'd like to include. To ensure your export reflects any filters you've applied, click Save for everyone before exporting.
  3. Click Import / Export on the top right of any view, then select Export view as CSV or Export view as Excel. Once downloaded, open the file in Excel, Google Sheets, Numbers, or any similar application.

Who can export

By default, all workspace members can export views on all records pages. Full access, read and write, and read only members can export views on lists. Workspace admins on the Enterprise plan can limit exports to admins only: Click your workspace name in the upper-left and choose Workspace settings from the dropdown. In the sidebar on the left, click Security. Under Advanced data controls, toggle on Disable data exports for non-admins.

Warning

The CSV export only includes columns visible in the current view. If you need all attributes, add every column before exporting. Hidden columns are silently omitted.

Formula injection protection

Attio includes an optional setting that protects against formula injection in CSV exports. It is available to workspace admins on all plans, and is disabled by default. Formula injection occurs when data containing spreadsheet formulas has been entered into a text attribute. When exported and opened in Excel or a similar application, those formulas may execute automatically. When this setting is enabled, Attio adds a prefix to text field values to prevent that from happening.

Important operational note: Enabling this protection prepends characters (typically a tab character \t or single quote ') to text values. If you're piping CSVs into an automated pipeline that expects raw strings, this will break field matching. Test against your downstream system before enabling in production.

CSV encoding and format details

Attio exports use UTF-8 encoding. Multi-select values are exported as comma-separated strings within a single cell. Linked record values are exported as display names (e.g., a company name), not as record IDs — which is why the API is required when you need to preserve relationship links. Date fields export in ISO 8601 format (YYYY-MM-DD).

How to run a full workspace backup

Attio's workspace export generates a downloadable ZIP file containing multiple CSV files covering your entire workspace. It is the closest thing to a full database dump that the Attio UI offers.

What's included in the workspace export

The workspace backup contains CSVs for:

  • Companies, People, Deals, Users, and Workspaces
  • Custom objects
  • Lists and list attributes
  • Attribute options (select/multi-select values)
  • Notes
  • Tasks
  • Comments
  • Files
  • Call recording activity (metadata only — no audio, video, or transcripts)
  • Workspace members

What's excluded

Data type Exportable via workspace backup? Alternative
Emails No Not exportable through any method
Meetings No API: GET /v2/meetings/{meeting_id}
Call recordings (audio/video/transcripts) No API: GET /v2/call-recordings/{call_recording_id}
Enriched attribute values No Manually overwrite first, or use API-to-custom-attribute workaround

Steps

  1. Click your workspace name in the upper-left and select Workspace settings.
  2. Under the General tab, click Start new export under Export Workspace data.
  3. Wait for the export to reach 100%, then click the download icon.

Workspace exports are restricted to admins. Non-admin users cannot trigger or download a workspace backup, regardless of their object-level permissions.

Workspace backup failure modes

  • Export stalls at 99%: This typically indicates a timeout on large workspaces. Retry during off-peak hours (overnight) when API load is lower. There is no partial resume — the export restarts from scratch.
  • ZIP file size: No documented maximum, but workspaces with 500k+ records and large file attachments have produced ZIPs exceeding several gigabytes. Ensure you have local disk space before downloading.
  • Encoding issues: All CSVs in the backup use UTF-8. If you're opening in Excel on Windows, use Data → From Text/CSV and specify UTF-8 explicitly to avoid mojibake on non-ASCII characters.
  • Missing custom object CSVs: If a custom object has zero records, it may be omitted from the ZIP entirely. Don't interpret absence as an export failure.
Tip

Run a workspace backup before any bulk operation — bulk deletes, migrations, or mass attribute changes. Attio has no native undo for bulk actions, and this ZIP is your safety net.

How to export data using the Attio API

The Attio REST API (v2) gives you full programmatic access to records, list entries, notes, tasks, and more in JSON format. Use it for automated CRM pipelines, migrating from systems not easily exported as CSV, or building custom integrations.

Authentication

The API uses OAuth 2.0 or API key authentication. For one-off exports and migrations, an API key is simpler. Generate one at Workspace Settings → Developers. For production integrations that access multiple workspaces, use OAuth 2.0.

Required scopes for a read-only export:

  • record_permission:read — to read records
  • object_configuration:read — to read object and attribute schemas
  • list_entry:read — to read list entries

Pagination

Attio uses offset-based pagination. The limit parameter controls the maximum number of results an endpoint can return. The offset parameter controls how many values to skip over in the result set, defaulting to 0.

Endpoint Default limit Maximum limit
List records (POST /objects/{slug}/records/query) 500 500
List record entries (GET /lists/{list_id}/entries) 100 1,000
List notes 100 100
List tasks 100 100

Offset pagination gap risk: If records are created or deleted mid-pagination, offset-based pagination can skip or duplicate records. For large exports, sort on created_at ascending and filter by a stable time range window to get a consistent snapshot. Alternatively, record all returned record_id values and deduplicate after collection.

A basic pagination loop in Python:

import requests
 
API_KEY = "your_api_key"
BASE = "https://api.attio.com/v2"
headers = {"Authorization": f"Bearer {API_KEY}"}
 
def export_all_records(object_slug: str):
    records = []
    offset = 0
    limit = 500
    while True:
        resp = requests.post(
            f"{BASE}/objects/{object_slug}/records/query",
            headers=headers,
            json={"limit": limit, "offset": offset},
        )
        resp.raise_for_status()
        batch = resp.json()["data"]
        records.extend(batch)
        if len(batch) < limit:
            break  # Last page reached
        offset += limit
    return records
Info

The List records endpoint accepts a filter_view_id parameter. Pass the UUID of a saved view, and results are filtered using that view's filter configuration. This cannot be used together with filter. Note: sorts, limits, and offsets are applied independently and are not taken from the view. All attributes are returned regardless of which attributes are visible in the view.

What enriched fields look like in API responses

Unlike CSV exports (where enriched fields are blank), the REST API does return enriched attribute values. In the JSON response, enriched attributes appear identically to user-entered attributes — there is no explicit is_enriched flag on the value itself. However, the attribute's schema (retrievable via GET /v2/objects/{object_slug}) includes metadata that identifies it as an enrichment-sourced attribute.

A record response with both enriched and non-enriched attributes looks like this:

{
  "id": {"record_id": "abc123"},
  "values": {
    "name": [{"value": "Acme Corp", "active_from": "2024-01-01T00:00:00Z"}],
    "description": [{"value": "Enterprise software company", "active_from": "2024-01-01T00:00:00Z"}],
    "employee_range": [{"value": {"option_title": "51-200"}, "active_from": "2024-01-01T00:00:00Z"}],
    "linkedin_url": [{"value": "https://linkedin.com/company/acme", "active_from": "2024-01-01T00:00:00Z"}]
  }
}

In this example, description, employee_range, and linkedin_url may be enriched fields — they look structurally identical to name. To distinguish them, query the object schema and check for enrichment metadata on each attribute definition.

This API-visible enriched data is what makes the Option 3 workaround (see below) functional: you can read the enriched value via API, write it into a custom non-enriched attribute, and then export it via CSV or backup.

What are Attio's API rate limits?

The Attio API applies rate limits to all API calls to ensure fair usage and maintain platform availability. The rate limit across the whole API is 100 requests per second for read requests and 25 requests per second for write requests.

That 100 reads/second ceiling sounds generous, but there's a second layer:

Attio's List records and List entries endpoints also utilize score-based rate limits. Each request receives a complexity score. The score is a function of the request's sorts and filters as well as the total record/entry count for the object/list. Scores may trigger rate limits in two ways: the score for an individual query may exceed the per-query limit (in which case, reduce the complexity of your query and try again), or the summed scores across multiple queries may exceed the limit for a given window of time. Attio uses a sliding window algorithm with a 10-second window. Scores are summed across all apps and access tokens using the API.

Score-based rate limit behavior in practice

The complexity score is not publicly documented as an exact formula, but observed behavior follows a consistent pattern:

Query type Object size Observed behavior
Unfiltered, unsorted < 10,000 records Rarely triggers score limit
Unfiltered, unsorted 50,000–100,000 records Occasionally triggers per-query limit
Filtered + sorted on indexed field 80,000 records Frequently triggers per-query limit at maximum limit (500)
Filtered + sorted on non-indexed field Any size High likelihood of per-query score limit
Unfiltered, paginating sequentially 100,000+ records Triggers windowed cumulative limit after ~40–50 sequential requests

Critical for multi-integration workspaces: If you're running multiple integrations against the same workspace (Zapier + a custom script + a sync tool), their complexity scores stack within the same 10-second window. Running a migration script while other integrations are active can push total scores over the windowed limit even when each individual script would be fine in isolation. Temporarily disable or throttle other API consumers during large extractions.

You will receive a 429 HTTP status and a Retry-After header when you hit any rate limit. Attio may occasionally reduce the rate limit as part of incident response, and may permanently lower it for specific APIs that handle large data volumes.

Retry-After header format

Important: The Retry-After header from Attio may be returned as an HTTP date string (e.g., Wed, 21 Oct 2025 07:28:00 GMT), not as an integer number of seconds. Most HTTP client libraries and retry implementations assume integer format. Parsing an HTTP date string as an integer will silently produce incorrect wait times (typically NaN or 0), causing immediate retry loops that accelerate rate limit exhaustion.

import time
from datetime import datetime, timezone
import requests
 
def request_with_backoff(method, url, **kwargs):
    for attempt in range(5):
        resp = method(url, **kwargs)
        if resp.status_code != 429:
            return resp
        retry_after = resp.headers.get("Retry-After")
        if retry_after:
            # Retry-After may be an HTTP date string, not an integer
            try:
                retry_date = datetime.strptime(
                    retry_after, "%a, %d %b %Y %H:%M:%S %Z"
                ).replace(tzinfo=timezone.utc)
                wait = (retry_date - datetime.now(timezone.utc)).total_seconds()
            except ValueError:
                # Fall back to treating as integer seconds
                wait = float(retry_after)
        else:
            wait = 2 ** attempt  # Exponential backoff if no header
        time.sleep(max(wait, 0.5))
    resp.raise_for_status()

What data types require the API to export?

Several Attio data types are only accessible via the API and cannot be exported through the UI at all:

  • Meetings: Retrievable through GET /v2/meetings/{meeting_id}. The workspace backup excludes them entirely.
  • Call recordings (audio/video/transcripts): Available through GET /v2/call-recordings/{call_recording_id}. The workspace backup only includes metadata.
  • Webhook configurations: Readable via API but there is no bulk event log endpoint. Webhook history is not exportable.
  • Record relationship graph: The UI export flattens relationships into display-name column values. The API returns linked record IDs (e.g., {"record_id": "abc123"}), which is what you need to reconstruct the relationship graph in a target system.

For migrations, the API's ability to preserve record IDs and relationship links is the critical difference between a flat data dump and a reconstructable data model.

Enriched data: the portability gap

Enriched data in Attio refers to attributes that Attio automatically populates from its own data sources — company descriptions, employee counts, social handles, logos, and similar fields. Attio automatically enriches person and company records with useful data points like logos and profile pictures, social media handles, and descriptions. When Attio has new data it will automatically update enriched attributes so your data is always current.

The catch: it is not possible to export enriched data from Attio. If you overwrite Attio's enriched data manually, data that you have entered yourself is able to be exported.

Enriched attributes are visually distinguished in the UI with lilac-colored cells and a sparkle icon in column headers. In CSV exports, those cells are blank regardless of what value is displayed in the UI.

Three workarounds, ranked by scalability:

Option 1 — Manual overwrite (impractical at scale): If you manually edit an enriched field, the value becomes "yours" and exports normally. Feasible for fewer than 50 records.

Option 2 — Third-party re-enrichment (best for ongoing use): Use a provider like Apollo, Clearbit, or Clay to re-enrich records after migration. Attio has a native Apollo enrichment integration that stores data in dedicated custom fields that are exportable. This is the right approach if you're migrating to a CRM that will also need ongoing enrichment.

Option 3 — API snapshot before export (best for large one-time migrations):

  1. Use the API to read all records including enriched field values (they are returned in API responses, as shown in the JSON example above).
  2. For each enriched attribute, write the value back into a custom non-enriched attribute of the same type (e.g., a text attribute named company_description_snapshot).
  3. Export those custom attributes via CSV or workspace backup.

This option is fully scriptable. A workspace with 20,000 company records can be snapshotted in under 30 minutes at 25 writes/second, accounting for rate limits.

Third-party export tools

Tool Method Output Best for
Coefficient Attio API via add-in Google Sheets / Excel Recurring live reports
Flatly Attio API CSV to cloud storage Automated backups
Zapier / Make Attio triggers + actions Any connected app Event-driven sync
Custom script Direct REST API JSON / CSV / database Full control, migrations

With Coefficient, you choose the object type (Contacts, Companies, or custom objects), select attributes, apply filters, and set a scheduled run to refresh data automatically. This is useful for dashboards and reporting but not for full migrations — the data arrives in spreadsheet format without relationship IDs.

For a complete data extraction that preserves record links, custom API scripts remain the most reliable approach.

How to plan a complete Attio data extraction

Threshold guidance before you start:

  • Under 5,000 records, no enriched data, one-time export: CSV export from views is sufficient. Total time: under 10 minutes.
  • 5,000–50,000 records, some enriched data: API extraction with pagination. At 500 records/request and 100 requests/second, pulling 50,000 records takes under 2 seconds of pure API time — but score-based limits and write-back for enriched fields will extend this to 15–30 minutes in practice.
  • 50,000+ records, complex relationships, enriched data: Budget 60–120 minutes for full extraction. Score-based rate limits become the primary constraint above this scale.
  • 100,000+ records across multiple objects: Expect 2–4 hours. Run extractions sequentially by object, not in parallel, to avoid stacking score-based limits.

A full extraction follows this sequence:

  1. Inventory your objects: List every object type (standard and custom) and count records per object using GET /v2/objects. Note which objects have enriched attributes.
  2. Map attributes: For each object, query GET /v2/objects/{slug} to document all attributes — including enriched ones. Plan your Option 3 workaround for enriched fields.
  3. Export structured data via API: Pull records per object with pagination, preserving record IDs. Pull list entries separately with their entry IDs.
  4. Export notes, tasks, and comments: These are linked to records via parent record IDs. Use the /v2/notes and /v2/tasks endpoints with record ID filters.
  5. Run a workspace backup as a safety net: Even with API as your primary extraction, the backup gives you a cross-reference.
  6. Validate completeness: Compare record counts between API response totals and workspace backup CSVs. Mismatches indicate pagination gaps (concurrent record creation/deletion) or rate-limit-induced missed pages.
Warning

Attio's API does not have a bulk export endpoint. You extract data object by object, paginated. For a workspace with 100,000+ records across multiple objects, budget 60–120 minutes for a full extraction depending on query complexity and rate limit headroom.

Common pitfalls when exporting from Attio

  • Enriched data blindspot: You'll export the CSV, open it, and find critical columns blank. Always check which attributes are enriched (lilac cells, sparkle icon) before relying on a CSV export.
  • View filter not saved: To ensure your export reflects any filters you've applied, click Save for everyone before exporting. Unsaved filters are ignored during export.
  • Score-based rate limiting with multiple integrations: Two integrations hitting the same workspace can starve each other within the 10-second scoring window. Temporarily disable other API consumers during large migrations.
  • Offset pagination gaps during concurrent writes: If records are created or deleted mid-pagination, you can skip or duplicate records. Sort on created_at ascending and use time-range filtering for consistent snapshots.
  • Retry-After as date string: Most HTTP clients expect Retry-After to be an integer. Attio may return an HTTP date string. Parsing a date string as a float returns NaN, causing immediate retry loops. Parse as shown in the code sample above.
  • Custom object CSVs missing from workspace backup: Objects with zero records may be omitted from the ZIP. Don't interpret absence as an export failure.
  • Formula injection prefix breaking pipelines: Enabling the formula injection protection setting prepends characters to all text values. This will break exact-match logic in downstream ETL pipelines. Test before enabling.

Method comparison summary

Criteria CSV export Workspace backup REST API
Access level All members (admins can restrict) Admins only API key required
Enriched data ❌ Blank cells ❌ Blank cells ✅ Returned in responses
Relationship IDs ❌ Display names only ❌ Display names only ✅ Preserved
Emails ❌ Not included ❌ Not included ❌ Not accessible
Meetings ❌ Not included ❌ Not included ✅ Via dedicated endpoint
Max records per operation View row limit Full workspace 500/request (paginated)
Output format CSV / Excel ZIP of CSVs JSON
Best for Quick snapshots, reporting Pre-migration safety net Migrations, integrations

Frequently Asked Questions

Can you export enriched data from Attio?
No. Attio's auto-enriched attributes (company descriptions, employee counts, social handles) export as blank cells in CSV and workspace backups. Manually overwritten values do export. To preserve enriched data during a migration, copy values into custom non-enriched attributes via the API before exporting.
What are Attio's API rate limits?
Attio allows 100 read requests per second and 25 write requests per second globally. List records and list entries endpoints also have score-based limits using a 10-second sliding window — complex filters and sorts consume more score. Exceeding limits returns HTTP 429 with a Retry-After header.
How do I do a full workspace backup in Attio?
Go to Workspace Settings → General → Export Workspace data and click Start new export. Attio generates a ZIP file with CSVs covering records, lists, notes, tasks, comments, files, and more. Only admins can run workspace exports. Emails, meetings, and call recordings are excluded.
What data is not included in Attio's workspace export?
The workspace export excludes emails (not exportable at all), meetings (API only), call recordings audio/video (API only — metadata is included), and all enriched attribute values. Use the Attio REST API for meetings and call recordings.
Does Attio have a bulk export API endpoint?
No. Attio does not offer a single bulk-export endpoint. You extract data object by object using paginated queries (default limit 500 records per page). For large workspaces with 100k+ records, a full API extraction typically takes 30–60 minutes depending on complexity and rate limit usage.

More from our Blog

The Ultimate Guide to Attio CRM (2026): From Setup to Full AI Automation
Attio

The Ultimate Guide to Attio CRM (2026): From Setup to Full AI Automation

Unlock the full potential of Attio CRM with our ultimate 2026 guide. This comprehensive overview covers everything from initial setup and data migration to mastering advanced AI automation and workflows. Learn how to leverage Attio's flexible data model and automatic relationship intelligence to transform your GTM strategy and create a single source of truth for your team.

Raajshekhar Rajan Raajshekhar Rajan · · 11 min read