n8n

How to Connect n8n and Clay

The mechanics of a two-way n8n and Clay integration: webhook contracts, payload design, correlation IDs, retries, idempotency, timeouts and how to test it.

Mauricio Esparza By ·Published ·6 min read
mithub.club
Short answer

You connect n8n and Clay with webhooks in both directions. n8n posts JSON to a Clay webhook table; Clay enriches and scores the row, then an HTTP API column posts the result back to a second n8n webhook. The work that makes it reliable is the contract between them: a correlation ID, a fixed payload shape, idempotency and a timeout sweep.

n8n and Clay connect through webhooks in both directions: n8n posts JSON into a Clay webhook table, Clay enriches and scores the row, and a Clay HTTP API column posts the result back to a second n8n webhook. The wiring takes an afternoon. What separates a demo from something you can hand to a colleague is the contract between the two systems — the correlation ID, the payload shape, the idempotency rule, the timeout and the error path.

This article is about those mechanics. For the strategic question of which tool owns which job, read Clay vs n8n first; for the tools themselves, What is n8n? and What is Clay?.

The shape of the integration

Clay is asynchronous by nature. A row can sit in a table for seconds or minutes while providers respond and AI columns run. n8n is event-driven and expects to finish. That mismatch is the single fact that determines the whole design:

Never wait for Clay inside the request that triggered the workflow. Fire, record, and let Clay call you back.

So the integration is two workflows, not one:

  • Workflow A — outbound to Clay. Trigger → validate → write a record with a status → POST to Clay → respond.
  • Workflow B — callback from Clay. Webhook → match by ID → apply the result → act → log.

Step 1: define the contract before you build

This is the part people skip. Write it in a shared doc and keep it next to the workflow. Five lines:

Contract itemExample
Correlation IDlead_id — the CRM record ID, created before the call to Clay
Payload outlead_id, email, phone, company_domain, source, received_at (ISO 8601)
Payload backlead_id, tier, reason, company_size, verified_email, clay_row_url
Idempotency ruleSecond callback with the same lead_id updates, never re-triggers outreach
Timeout20 minutes; after that a sweep routes the lead with tier = default

The correlation ID is the load-bearing element. Without it, a callback is an orphan: you have an enriched record and no idea which lead it belongs to. Create the CRM record first, precisely so you have an ID to send.

If JSON payloads and HTTP verbs are unfamiliar territory, APIs, webhooks and JSON for non-developers covers the vocabulary.

Step 2: n8n → Clay

In Clay, add a webhook source to a workbook. Clay generates a unique URL that receives HTTP POST requests in JSON, and it supports an optional authentication token in the request headers (Webhooks in Clay). Copy that URL into n8n credentials or a variable — not into a node parameter you'll later screenshot for a colleague.

In n8n, use an HTTP Request node with method POST, a JSON body, and the token in a header. The node supports predefined and generic credential types, including Header auth, so the token never lives in the body of the workflow (HTTP Request node).

POST <the webhook URL Clay generated for your table>
Headers: <the auth header name and token Clay gave you>

{
  "lead_id": "CRM-88213",
  "email": "maria@example.com",
  "phone": "+1 706 555 0142",
  "company_domain": "example.com",
  "source": "website-form",
  "received_at": "2026-09-17T14:03:11Z"
}

Three habits that pay off later:

  • Send a flat payload. Nested objects are harder to map into columns and harder to read in a failed execution.
  • Send fields even when empty, as null or "". A field that sometimes doesn't exist breaks downstream expressions in ways that are annoying to debug.
  • Timestamp everything in ISO 8601, in UTC. Timezone drift between two platforms is a genuinely miserable bug.

One planning note: Clay's docs state that webhook sources are limited to 50,000 submissions, and that the limit persists even after deleting rows, with auto-delete passthrough tables available on Enterprise plans (Clay Docs). For a high-volume feed, plan for table rotation rather than discovering the ceiling at 3am.

Step 3: batching and backpressure

If you're pushing a list rather than single leads — say 2,000 rows from a CRM query — don't fire 2,000 requests as fast as n8n can loop.

The HTTP Request node exposes batching options, Items per Batch and Batch Interval (in milliseconds), plus a Timeout setting for the initial response (n8n Docs). Use them. On the Clay side, the HTTP API column has configurable rate limiting — the docs show a request limit over a duration, with an example of 10 requests per second — and a retry-on-failure option (Clay HTTP API).

Set both sides deliberately, and write the chosen numbers in the contract doc. "It worked when I tested with five rows" is how integrations fail at scale.

Step 4: Clay → n8n, the callback

Inside Clay, the last column of the table is an HTTP API column set to POST against your n8n Webhook node's production URL. Clay's HTTP API supports GET, POST, PUT and DELETE, custom headers, a JSON body, and field paths to extract values from responses (Clay Docs).

Two details from those docs matter for security and sanity:

  • Credentials typed into the Headers field are visible in plain text to anyone with access to the column. Clay offers secure account storage instead — use it.
  • Gate the callback column. Run it only when the row is complete, otherwise n8n receives half-finished rows and your callback workflow needs defensive logic it shouldn't need.

On the n8n side, the receiving Webhook node should authenticate the caller. The node supports Basic auth, Header auth, JWT auth or none (Webhook node) — pick header auth at minimum, and respond immediately rather than after the workflow finishes. Details and the security checklist are in n8n webhooks explained.

Step 5: idempotency — the rule that prevents embarrassment

Retries are good. Retries plus a non-idempotent workflow means the same person gets called twice.

Make the callback workflow idempotent in one of two ways:

  1. Check state before acting. Look up the record; if its status is already scored, update fields and stop. Only records in enriching proceed to outreach.
  2. Deduplicate on the ID. n8n's Remove Duplicates node can remove items processed in previous executions, keeping a history scoped to the node or to the workflow, with a default history of 10,000 items (n8n Docs). Feed it the lead_id.

Option 1 is more explicit and survives history limits; option 2 is faster to build. On anything that spends money or contacts a human, use option 1.

Step 6: failure, timeouts and the sweep

Two things will happen in production: a row will error inside Clay, and a callback will never arrive.

  • Errors inside n8n: set an error workflow. When an execution fails, n8n runs the linked workflow, which must start with the Error Trigger node (Handle errors gracefully). Send yourself the workflow name, the failing node and the execution URL — not just "workflow failed."
  • Missing callbacks: a scheduled workflow that queries for records with status enriching older than the timeout in your contract, routes them with a default tier, and flags them for review. Without this, leads disappear silently, which is the worst failure mode because nobody notices.

The production-grade version of all of this — dead-letter patterns, alert design, retry settings per node — is in n8n error handling for production workflows.

The debugging table

When the integration misbehaves, work in this order rather than guessing:

SymptomLook here firstUsual cause
Nothing arrives in Clayn8n execution → HTTP Request node outputWrong URL, missing auth header, workflow not published
Row appears, columns emptyClay cell-level errorsMissing input field, column condition never true
No callbackClay HTTP API column outputColumn gated off, endpoint using the test URL, auth rejected
Callback arrives, nothing happensn8n execution list for workflow BID mismatch, record already in a later status
Everything green, nothing in the CRMThe CRM record itselfThe classic: a successful run with an empty result

That last row deserves its own sentence. A green execution is not a business result. Once a week, take three leads and follow them end to end: form, CRM record, Clay row, callback, action, outcome. This is the observe-and-measure habit from Operate, and it catches the failures monitoring never will.

A 90-minute build plan

  1. Minutes 0–15: write the contract. Five lines. Don't open either tool yet.
  2. 15–35: build the Clay webhook table with three columns: input, one enrichment, one score.
  3. 35–55: build workflow A in n8n: trigger, validate, create record with status, POST to Clay.
  4. 55–75: add the Clay HTTP API callback column and workflow B in n8n: webhook, match by ID, update, act.
  5. 75–90: break it on purpose. Send a bad payload. Send the same payload twice. Delete the callback URL. Fix what you find, then add the error workflow and the sweep.

Step 5 is the one that turns a wiring exercise into engineering. If you want to practise this on a real process instead of a toy one, that's exactly what the Faculty of Revenue Reverse Engineering is for.

Frequently asked questions

How does n8n send data to Clay?

Add a webhook source to a Clay workbook, copy the generated URL, and post JSON to it from an n8n HTTP Request node. Clay's docs describe receiving HTTP POST requests in JSON and support an optional authentication token in the request headers.

How does Clay send data back to n8n?

With an HTTP API column set to POST against an n8n Webhook node's production URL. Clay's HTTP API supports GET, POST, PUT and DELETE, custom headers, a JSON body and stored credentials so keys are not visible in the column.

How do I stop the same lead being processed twice?

Send a stable correlation ID with every payload and make the receiving side idempotent. In n8n, the Remove Duplicates node can discard items already processed in previous executions, keeping a history per node or per workflow.

What if Clay never calls back?

Assume it sometimes won't. Write the record with a status like 'enriching' before you send it, and run a scheduled n8n workflow that finds records stuck in that status and routes them with a default outcome.

Is there a limit on Clay webhook tables?

Clay's documentation states that webhook sources are limited to 50,000 submissions and that the limit persists even after deleting rows, with an auto-delete option available on Enterprise plans.

Sources

  1. Webhooks in Clay — Clay Docs (accessed 2026-09-17)
  2. HTTP API integration overview — Clay Docs (accessed 2026-09-17)
  3. Webhook node — n8n Docs (accessed 2026-09-17)
  4. HTTP Request node — n8n Docs (accessed 2026-09-17)
  5. Remove Duplicates node — n8n Docs (accessed 2026-09-17)
  6. Handle errors gracefully — n8n Docs (accessed 2026-09-17)
n8nClayWebhooksIntegration Design
Mauricio Esparza
Mauricio EsparzaGTM Systems Lead · Revenue Engineer · Founder of MitHub. Designs and runs revenue systems for multi-location businesses: AI voice campaigns, enrichment, CRM automation and attribution. Founded MitHub to teach the method in the open.

Part of n8n on MitHub.

Keep going