Playbooks / Skill & signal
n8n: Enrich Over HTTP, Then Push to HubSpot With n8n's Own Node
An n8n workflow with two owners: the enrichment half is an HTTP Request node hitting RichAPI, and the HubSpot half is n8n's built-in HubSpot node. We have no HubSpot app, so nothing in this workflow writes to your CRM except n8n itself. Costs are scoped per endpoint: email_finder and email_verifier are waterfall and do not bill on a miss, everything else bills on any 2xx.
Pattern: Trigger (schedule, webhook, or a Sheets row) → HTTP Request to /email_finder → IF on success → HTTP Request to /email_verifier → n8n HubSpot node, Contact: Create or Update. Two HTTP nodes you configure once and one CRM node n8n maintains.
In short: RichAPI is called from n8n's generic HTTP Request node to enrich contact records, which n8n's own built-in HubSpot node then writes to HubSpot. RichAPI does not publish a HubSpot application or a CRM-native integration; the HubSpot leg is provided entirely by n8n. RichAPI is called from n8n's generic HTTP Request node against https://api.richapi.ai/api/v1/, authenticated with an x-api-key header configured as an n8n Header Auth credential. The workflow calls /email_finder, branches on the success field with an IF node, calls /email_verifier on the success branch, then calls the HubSpot node with Contact Create or Update keyed on email. email_finder and email_verifier are waterfall endpoints: when sources run and none return data the response is HTTP 200 with success:false and billed:false, costing zero credits. All other RichAPI endpoints, including enrich_profile and enrich_company, bill on any 2xx response including an empty result. A community-maintained n8n node named n8n-nodes-richapi exists at version 0.1.3; it is a community node, not verified or built into n8n, and it is not maintained by RichAPI. New accounts get 100 free credits with no credit card.
Last updated November 4, 2026
Credit math
500 rows through the enrichment half: email_finder at 5 credits bills only on the rows that produced an address. At a 60% hit rate that is 300 × 5 = 1,500 credits, and the 200 misses cost zero because email_finder is a waterfall endpoint. email_verifier at 2 credits runs on the 300 found addresses for 600 credits. 2,100 credits for 500 rows. The 60% is an illustration; measure your own on 100 rows first. If you add enrich_profile at 1 credit it bills on every 2xx including an empty one, so budget it at 500 × 1, not 300 × 1.
ROI math
The saving here is that the enrichment half is four fields in an HTTP node instead of a connector you wait on a vendor to ship. Against a per-seat enrichment tool, compare seats you would need versus a workflow that runs unattended. Credit tiers on /pricing.
Owned internally by
Whoever already owns the n8n instance. No engineer needed for the HubSpot half, because n8n's node does the OAuth.
Best for
Teams self-hosting n8n who want CRM writes without buying a CRM-native enrichment seat, and anyone whose HubSpot is already connected in n8n.
- 01
Store the key as an n8n Header Auth credential named x-api-key.
Do not paste it into the node body, where it ends up in every exported workflow JSON and every screenshot you send to support.
- 02
Build the /email_finder HTTP Request node and pin one real row of sample data so you can see the response shape before wiring anything downstream.
- 03
Add an IF node reading {{ $json.success }}.
A miss returns HTTP 200 with success:false, so n8n's own 'continue on fail' setting will not catch it. This IF is the only thing standing between a miss and a blank email written to HubSpot.
- 04
Add the /email_verifier HTTP Request node on the true branch only.
- 05
Add n8n's HubSpot node, operation Contact: Create or Update, keyed on email.
Authenticate it with n8n's HubSpot OAuth credential. This leg is entirely n8n's; we have no HubSpot app.
- 06
Send the false branch somewhere visible, a Sheet or a Slack node, rather than dropping it.
Unfindable rows are a list-quality signal and you want to see the rate.
- 07
Run the workflow on 20 rows manually before you put it on a schedule.
n8n loops fast and an unbounded schedule trigger on a 4,000-row source is the usual way people discover their credit balance.
# The enrichment half is an HTTP Request node. This is the same call,
# as curl, so you can test it before you build the node.
curl -s https://api.richapi.ai/api/v1/email_finder \
-H "x-api-key: $RICHAPI_KEY" \
-H "content-type: application/json" \
-d '{
"first_name": "Dana",
"last_name": "Weiss",
"company_domain": "acme.com",
"company_name": "Acme"
}'
# In the n8n HTTP Request node:
# Method: POST
# URL: https://api.richapi.ai/api/v1/email_finder
# Authentication: Generic Credential Type -> Header Auth
# Header name: x-api-key
# Body: JSON, with expressions: {{ $json.first_name }} etc.
#
# Then an IF node on {{ $json.success }} = true before the verifier node,
# and the HubSpot node after that. The HubSpot node is n8n's, not ours.
n8n: enrich over HTTP, then push to HubSpot with n8n's own node
This workflow has two owners and it's worth being clear about which half is ours before you build it.
The enrichment half is ours: an HTTP Request node pointed at https://api.richapi.ai/api/v1/email_finder, a header, a JSON body. The HubSpot half is n8n's: their HubSpot node, their OAuth credential, their field mapping. We do not have a HubSpot app. Nothing in this workflow writes to your CRM on our behalf. If n8n's HubSpot node breaks, that's a conversation with n8n.
That's not a hedge, it's the design. See HubSpot for what we do and don't do there, and n8n for the node setup in full.
About the community node
There is an npm package called n8n-nodes-richapi, currently v0.1.3. It exists, it works, and someone in the community built it. It is not verified, not built into n8n, and not maintained by us. On n8n Cloud, community nodes are restricted; on self-hosted you install it yourself and you own the upgrade path.
Use it if you like fewer boxes on a canvas. Use the plain HTTP Request node if you want the thing to still work in six months without checking whether a volunteer is still shipping. We build these pages around the HTTP node for that reason.
Building it
Five nodes. Trigger, finder, IF, verifier, HubSpot.
The only node with any subtlety is the IF. A miss on /email_finder returns HTTP 200 with success: false and billed: false. n8n's error handling never sees it, because there is no error. If you skip the IF and map {{ $json.email }} straight into the HubSpot node, you will write empty strings over contacts that already had good addresses, and HubSpot will happily accept them.
Branch on success. That's the whole trick.
What each leg costs, and where the free part stops
/email_finder and /email_verifier are waterfall endpoints: several sources run cheapest-first, and if every one of them comes back with nothing, you get a 2xx with billed: false and pay zero.
That is a narrow claim and it does not extend to the rest of the workflow. If you add /enrich_profile at 1 credit to pull a title, it bills on any 2xx, including one that comes back thin. Budget it per row attempted, not per row that worked. Same for /enrich_company at 1 credit, which takes a LinkedIn company URL rather than a domain, so you need that URL on the row already.
Every waterfall response carries an execution_log showing each step that ran on that request. Log it to a Sheet from the false branch; it's the only record of why a row missed and it can't be reconstructed later.
The failure mode: the schedule trigger nobody bounded
The IF-node bug costs you data quality. This one costs you money.
Somebody builds the workflow, tests it on five rows, sets a Schedule Trigger to every 15 minutes, and points it at a Google Sheet that grows. The workflow has no "already enriched" column, so every run re-enriches every row. n8n does not care. It will do this cheerfully until someone notices.
Add a enriched_at column, filter on it before the finder node, and write it back after the HubSpot node. It's one extra Sheets node and it is the difference between a workflow and a leak. Re-running a row you already resolved is the most common way to spend credits twice, in n8n more than anywhere else, because n8n makes looping so easy.
Where the n8n to HubSpot flow goes wrong
No sending. The contact lands in HubSpot and your sequencer takes over from there. No dedupe beyond whatever HubSpot's email-keyed upsert does. No intent data, no scoring.
And there is no CRM-native app. If what you actually want is a button inside HubSpot, we don't have one, and HubSpot says so plainly.
The n8n to HubSpot flow FAQ
Can I use the community node instead of HTTP Request? Yes, on self-hosted n8n. n8n-nodes-richapi v0.1.3 installs like any community node. It is not ours and it is not verified by n8n, so treat it as a convenience, not a dependency.
Does this work on n8n Cloud? The HTTP Request approach does, unchanged. The community node runs into n8n Cloud's community-node restrictions.
Why not just use n8n's HubSpot node to enrich? HubSpot's own enrichment is a HubSpot product with HubSpot's pricing. This workflow exists for people who don't want that seat.
Where do I put the key? An n8n Header Auth credential, name x-api-key. Workflow JSON gets exported and shared far more often than people expect.
What if a row has a LinkedIn URL instead of a domain? Send linkedin_url to /email_finder instead of name plus domain. Same price, better hit rate.
Where to go after the n8n to HubSpot flow
n8n for node-by-node setup, HubSpot for the CRM boundary, waterfall email then verify for the billing detail on both legs, zapier email find on form fill if you're on Zapier instead, and use cases for the rest of the plays. Credit tiers on pricing.
100 free credits, no card. Enough to run the workflow on a handful of rows and watch a miss cost nothing.
FAQ