automationcrmenrichment

Attio + n8n CRM Enrichment Workflow (2026 Guide)

TL;DR

Connect Attio to n8n via webhook or API node, trigger enrichment through Clay or FullEnrich on new record creation, then write structured data back to Attio custom attributes automatically.

On this page

Most RevOps teams I talk to are still running enrichment as a manual task. Someone exports a CSV, uploads it to Apollo or Clay, downloads the result, and pastes it back into the CRM. If you have moved to Attio as your CRM, you do not have to accept that. Attio’s REST API is clean, its webhook automation triggers are reliable, and n8n can sit in the middle and orchestrate every enrichment provider you want without a line of Python. This guide walks through the exact workflow I use with clients who run Attio as their system of record and want enrichment that fires within 90 seconds of a record hitting the database.

Why Attio Plus n8n Is Worth the Setup Time

Attio is not HubSpot with a fresh coat of paint. Its data model is genuinely different. Records, lists, and attributes are first-class objects, and its API reflects that. When you create a Contact or a Company record, Attio fires a configurable automation that can POST a webhook payload with the full record JSON. That is your trigger. No polling loop, no Zapier in the middle, no third-party Attio connector to pay for.

On the n8n side, the Webhook node receives that payload, and from there you have the full canvas to route, enrich, branch, and write back. I prefer n8n over Make for Attio workflows for one specific reason: self-hosting. Enrichment data never touches a third-party EU-violating server, and the HTTP Request node handles Attio’s REST API with zero friction. Make’s per-operation pricing also gets painful fast once you add confidence-score branching and Slack alerts to the flow.

90s
Median enrichment lag
Time from Attio record creation to enriched data written back, in a production n8n workflow with FullEnrich
3-5x
Data coverage improvement
Waterfall enrichment via Clay across Apollo, Clearbit, and FullEnrich versus any single provider alone
$0
n8n self-hosted cost
Run the orchestration layer on a $6/mo VPS; pay only for enrichment API credits consumed

The enrichment layer is where you choose your weapon. For most of my clients I recommend a waterfall: try FullEnrich first for mobile and direct email (it is cheaper per credit and has strong European coverage), then fall through to Clay for everything else including firmographic data. If you want the single-vendor approach, Clay alone covers most use cases. I will show both paths below.

n8n workflow canvas with webhook trigger, enrichment step, ICP branch, and write-back nodes
The n8n workflow canvas showing a webhook trigger feeding into enrichment and then branching back to Attio via HTTP Request nodes.

The Workflow, Step by Step

Before you build: you need an Attio workspace on Plus or above for API access, an n8n instance (cloud or self-hosted), and API keys for your enrichment provider. Attio API keys live under Settings > API. You want a Bearer token scoped to read/write on Contacts and Companies. If you are connecting this to an existing Clay enrichment pipeline, you can reuse the same Clay table and just add Attio as the write destination.

Step 1
Create the Attio webhook automation

In Attio, go to Automations and create a new trigger on 'Record created' for either Contacts or Companies (build one workflow per object). Set the action to 'Send webhook' and paste in your n8n Webhook node URL. Include the full record in the payload: record ID, email, name, domain, and any attributes already populated. Test it by creating a dummy contact and confirming the n8n execution log shows the incoming JSON.

Step 2
Configure the n8n Webhook node

Set the Webhook node to POST, choose 'Respond immediately' so Attio does not time out waiting, and use a unique path like /attio-contact-created. In the next node, add a Set node to extract the fields you need: record_id, primary_email (it lives inside an array in Attio's payload as values[0].email_address), and domain from the company association. Normalizing these early prevents parsing errors downstream.

Step 3
Call FullEnrich or Clay for enrichment data

For FullEnrich: add an HTTP Request node, POST to https://api.fullenrich.com/v1/enrich/person with the email and domain in the body, and add your API key as a Bearer header. FullEnrich returns mobile, direct email, LinkedIn URL, and job title in a single call. For Clay: trigger a Clay table row via their webhook-to-table integration or use Clay's HTTP API to push the contact in and poll back. The Clay path gives you waterfall enrichment across 10+ sources but adds 5-15 seconds of latency. I use FullEnrich for speed on individual triggers and Clay for batch backfills.

Step 4
Branch on data quality

Add an IF node after the enrichment response. If confidence score is below 80 (FullEnrich returns a confidence field) or if the email field is null, route to a Slack notification node that posts to #revops-alerts with the Attio record URL. If enrichment succeeded, pass the clean data to the write-back node. This prevents garbage data from entering Attio silently, which is the failure mode I see most often in clients' existing workflows.

Step 5
Write enriched data back to Attio via PATCH

Add an HTTP Request node. Method: PATCH. URL: https://api.attio.com/v2/objects/people/records/ followed by the record_id (inject from Step 2 using an n8n expression). Headers: Authorization Bearer your_token, Content-Type application/json. Body: a JSON object with the attributes you want to write, using Attio's attribute slug format. To write a phone number to the mobile_phone attribute, send { 'data': { 'values': { 'mobile_phone': [{ 'phone_number': '+15551234567' }] } } }. Test with a real record ID before going live.

The gotcha that kills most first attempts: Attio’s API returns email addresses nested inside a values array, not as a flat string. If you try to pass body.email directly from the webhook payload, you get undefined, enrichment fails silently, and the record stays blank. I have debugged this exact issue for three separate clients who built the workflow independently and hit the same wall.

// Attio webhook payload shape (Contact)
{
  "record": {
    "id": { "record_id": "abc123" },
    "values": {
      "email_addresses": [
        {
          "email_address": "founder@acme.com",
          "is_primary": true
        }
      ],
      "name": [{ "full_name": "Jane Smith" }]
    }
  }
}

// n8n expression to extract primary email:
// {{ $json.record.values
//     .email_addresses
//     .find(e => e.is_primary)
//     .email_address }}

Choosing Your Enrichment Layer

The orchestration is n8n regardless. The decision is which enrichment provider sits in the middle. Here is how I frame it for clients.

Pick your enrichment provider

Choose FullEnrich if

  • You need mobile numbers and direct dials with strong EU coverage
  • You want a fast single API call per contact (no table setup)
  • Your volume is under 50k contacts per month and cost per credit matters

Choose Clay if

  • You need waterfall enrichment across Apollo, Clearbit, LinkedIn, and more in one place
  • You are doing batch backfills of thousands of existing Attio records
  • Your team already uses Clay tables as a staging layer before CRM entry
From $149/mo Try Clay →

For the Clay enrichment pipeline approach, the n8n workflow pushes records into a Clay table via webhook, Clay runs its waterfall enrichment (which Gartner research on data quality consistently shows outperforms single-source lookups by 40-60% on coverage), and then n8n polls or receives a Clay webhook back before writing to Attio. It is a two-hop architecture. The data quality improvement is worth it for outbound-heavy teams.

If you are enriching Companies rather than Contacts, Attio’s company object API uses a slightly different URL path (/v2/objects/companies/records/<id>) and the domain attribute is the most reliable lookup key. Use the domain to pull firmographics from FullEnrich or Clay and write headcount, industry, funding stage, and tech stack back as custom attributes.

For teams also running n8n for lead routing out of HubSpot, the same HTTP Request node pattern applies: authenticate with Bearer, PATCH the record, handle errors with a branch. The mental model transfers directly.

Backfilling Existing Records

New record enrichment is the easy part. Backfilling 10,000 existing Attio contacts is where teams get stuck. My approach: use Attio’s list filtering API to pull all records where mobile_phone is empty, paginate through them in n8n using a Loop Over Items node, and throttle to 10 requests per second to stay inside both Attio’s rate limit (60 requests per minute on Plus) and your enrichment provider’s limit. Schedule this as an n8n workflow on a cron trigger running nightly until the backfill completes.

Don’t try to run the backfill as one giant batch. I watched a client hammer Attio’s API with 8,000 simultaneous PATCH requests and get rate-limited for six hours. Ten records per second, paced with a Wait node set to 100ms, finishes 10,000 records in under three hours without a single 429.

Ship It, Then Tune It

This workflow takes about four hours to build from scratch. Thirty minutes on the Attio automation, 90 minutes on the n8n canvas including testing, 30 minutes tuning the enrichment provider configuration, and 60 minutes on the write-back validation logic. After that, it runs without intervention. I have clients who have had this workflow running for eight months with zero maintenance beyond rotating API keys once.

The next layer worth adding, once this is stable, is a scoring node after enrichment. Pull the enriched firmographics, run them against your ICP definition in an n8n Function node, write an icp_score attribute back to Attio, and trigger a different Attio automation for high-score records that notifies the AE. That is the full signal-to-action loop, entirely code-light once the enrichment plumbing is in place. For teams also tracking website visitor signals into their CRM, the Vector n8n visitor signal workflow uses the same Attio write-back pattern and slots cleanly into this architecture.

Sources

Filed under:

automationcrmenrichment

Frequently asked questions

Does Attio have a native n8n integration?

Not as a packaged node yet. You connect Attio to n8n using the HTTP Request node with Attio's REST API and a Bearer token from your Attio workspace settings.

What data can you write back to Attio from n8n?

Any Attio attribute you define, including custom ones. Common enrichment fields are company headcount, funding stage, tech stack, LinkedIn URL, and email confidence score.

Is Clay required for this workflow?

No. Clay is optional but powerful for waterfall enrichment. FullEnrich or direct Apollo API calls work fine if you want fewer moving parts.

How do I trigger the n8n workflow when a new contact is added to Attio?

Use an Attio automation in the platform to POST a webhook to your n8n webhook trigger URL whenever a record matches your trigger condition.

What Attio plan do I need for API access?

API access is available on Attio's Plus plan and above. The free tier does not expose the REST API for programmatic writes.


← Back to Blog

Enjoying this? Share it with your team.

Some links are affiliate links. Disclosure.