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 item | Example |
|---|---|
| Correlation ID | lead_id — the CRM record ID, created before the call to Clay |
| Payload out | lead_id, email, phone, company_domain, source, received_at (ISO 8601) |
| Payload back | lead_id, tier, reason, company_size, verified_email, clay_row_url |
| Idempotency rule | Second callback with the same lead_id updates, never re-triggers outreach |
| Timeout | 20 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
nullor"". 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:
- Check state before acting. Look up the record; if its status is already
scored, update fields and stop. Only records inenrichingproceed to outreach. - 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
enrichingolder 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:
| Symptom | Look here first | Usual cause |
|---|---|---|
| Nothing arrives in Clay | n8n execution → HTTP Request node output | Wrong URL, missing auth header, workflow not published |
| Row appears, columns empty | Clay cell-level errors | Missing input field, column condition never true |
| No callback | Clay HTTP API column output | Column gated off, endpoint using the test URL, auth rejected |
| Callback arrives, nothing happens | n8n execution list for workflow B | ID mismatch, record already in a later status |
| Everything green, nothing in the CRM | The CRM record itself | The 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
- Minutes 0–15: write the contract. Five lines. Don't open either tool yet.
- 15–35: build the Clay webhook table with three columns: input, one enrichment, one score.
- 35–55: build workflow A in n8n: trigger, validate, create record with status, POST to Clay.
- 55–75: add the Clay HTTP API callback column and workflow B in n8n: webhook, match by ID, update, act.
- 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.
