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.

  1. 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.

  2. 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.

  3. 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.

  4. 04

    Add the /email_verifier HTTP Request node on the true branch only.

  5. 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.

  6. 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.

  7. 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.

Example
# 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

Frequently asked

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.
The HTTP Request approach does, unchanged. The community node runs into n8n Cloud's community-node restrictions.
HubSpot's own enrichment is a HubSpot product with HubSpot's pricing. This workflow exists for people who don't want that seat.
An n8n Header Auth credential, name `x-api-key`. Workflow JSON gets exported and shared far more often than people expect.
Send `linkedin_url` to `/email_finder` instead of name plus domain. Same price, better hit rate.

More playbooks

Related playbooks

People Search to Email Waterfall: One Billing Model Per LegSearch builds the list; the finder and verifier resolve it. The search leg bills per result whether or not you end up using the row, while the other two are waterfall endpoints and cost zero on a miss. Three calls, two billing models, and the search leg is the one that charges you for rows you throw away.One key per client: what that buys an agency, and what it does notIssue a named API key per client, revoke any one of them without touching the others, and read usage attributed per key with a CSV export. What does not exist: per-client credit budgets, billed sub-accounts, and per-key spend caps. All credits come from one team balance, so a runaway job on one client's key spends the whole agency's credits. Budget enforcement lives in your scheduler, not in ours.Phone Append After an Email Hit: The 25-Credit Call That's Free When It MissesFind the email first, then append a phone number only to the rows that resolved. Both legs are waterfall endpoints, so both return `billed: false` and cost zero when sources find nothing. At 25 credits, the phone call is the most expensive in the catalog, which is exactly why the miss-free rule carries most of the value here.Turn a list of emails into enriched LinkedIn profilesResolve each email to a LinkedIn profile URL with find_linkedin_url_by_email, then enrich that URL with enrich_profile. Two calls, two charges. Neither one is a waterfall endpoint, so both bill on any 2xx — including a lookup that resolves nothing.