Integrations · HubSpot
RichAPI has no HubSpot marketplace app and no CRM-native install. You enrich in your own workflow, middleware or backend, then write to HubSpot yourself with their API. This page is the three ways to do that, and what each one costs on both meters.
Last updated September 22, 2026
Accept the shape first: there is nothing to install from the HubSpot marketplace.
Every path below ends with you writing to HubSpot's own CRM API.
Create a RichAPI account at app.richapi.ai/signup and copy your API key.
25 free credits, no card.
Create a HubSpot private app with the crm.objects.contacts.write and crm.objects.companies.write scopes and copy its access token. That token is what writes the enriched fields back.
Create the destination properties in HubSpot before your first run — enriched_email, enrichment_status, enriched_at — so a failed lookup has somewhere honest to land.
Pick a path: Operations Hub custom code action inside a HubSpot workflow, a middleware scenario in Make/Zapier/n8n, or a job in your own backend.
Write only when success is true.
Never let a miss overwrite a field a human filled in.
Copy, paste, edit the brackets, run.
Why it matters
Marketplace enrichment apps bill per record touched and quietly overwrite fields your reps corrected by hand. Running the lookup yourself means you decide what a miss does, and on the waterfall endpoints the miss costs nothing.
**RichAPI is not in the HubSpot marketplace.** There is no app to install, no OAuth connect button, no native "Enrich" action sitting in the HubSpot workflow editor with our name on it. If you arrived expecting a two-click install, stop reading here or read on, because the rest of this page is the integration: you call our API from somewhere you control, then write the result into HubSpot using HubSpot's own API. That is a real gap, and we are not going to dress it up. It also has one property the marketplace apps do not: you decide what happens on a miss. Every app that writes to your CRM automatically will, sooner or later, write a guessed email over one a rep confirmed on a call.
Create a **private app** in HubSpot with `crm.objects.contacts.write` and `crm.objects.companies.write`, and keep its token wherever you keep secrets. Then create the properties before the first run: - `enriched_email` — never write into HubSpot's own `email` field directly on the first pass. - `enrichment_status` — `found`, `not_found`, `error`. A miss needs a place to land. - `enriched_at` — a timestamp, so you can re-run only what is stale. Skip this and you cannot answer the first question anyone asks six weeks in: which of these records did the robot touch?
If your portal has the workflow **custom code** action, this is the shortest route. The action runs Node or Python inside the workflow, so the lookup and the property write happen in one step, on HubSpot's own enrolment logic. ```js exports.main = async (event, callback) => { const res = await fetch("https://api.richapi.ai/api/v1/email_finder", { method: "POST", headers: { "x-api-key": process.env.RICHAPI_KEY, "content-type": "application/json" }, body: JSON.stringify({ first_name: event.inputFields.firstname, last_name: event.inputFields.lastname, domain: event.inputFields.domain }) }); const body = await res.json(); callback({ outputFields: { enriched_email: body.success ? body.data.email : "", enrichment_status: body.success ? "found" : "not_found" } }); }; ``` Store the key as a workflow secret, not inline. The `outputFields` then map to properties in a following action, and you branch the workflow on `enrichment_status` like any other property. HubSpot's plain "send a webhook" action is the trap here: getting a custom auth header onto it is not something you should assume works. Custom code takes the header without argument.
No Operations Hub, or you would rather keep the logic outside the CRM: run the call in [Make](/integrations/make), [Zapier](/integrations/zapier) or [n8n](/integrations/n8n), each of which has a real HubSpot connector for the write half. The trigger is a HubSpot workflow webhook or a polling search; the middle is our HTTP call; the end is their HubSpot module. This is the most common setup and the easiest to debug, because both halves show you their payloads.
A cron job, a queue worker, or the function behind your own admin panel. Read the HubSpot search API for contacts missing an email, call us, batch the writes back. This is the only path that handles tens of thousands of records without fighting someone's task limits, and it is maybe eighty lines.
| Endpoint | Cost | Miss | | --- | --- | --- | | `email_finder` | `5 credits` | Free | | `email_verifier` | `2 credits` | Free | | `phone_finder` | `25 credits` | Free | | `enrich_company` | `1 credit` | Bills on 2xx | | `find_linkedin_url_by_email` | `4 credits` | Bills on 2xx | Free misses are a property of the multi-provider waterfall endpoints only. `enrich_company` and `enrich_profile` bill on any successful response, and both take a **LinkedIn URL** rather than a domain — a detail that sends people down a dead end when the HubSpot record only holds a website. Rates are on [pricing](/pricing). The waterfall response carries an `execution_log` listing each provider attempt and its status, which is the thing to write into a note or a custom property when a rep asks why a contact came back empty.
Enrichment is not a one-time migration. Run it on entry, not on every record every night: filter on `enriched_at` older than six months, and on properties that are actually empty. A nightly full-table sweep of 40,000 contacts through `phone_finder` is the single most expensive mistake available to you here, and nothing in this design stops you making it.
We do not write to HubSpot. We do not read from HubSpot. We do not send email, we have no sequencer, and we have no CRM-native app for HubSpot or anyone else. We return data over HTTP; the CRM half is yours. If you want the same lookups without any of this plumbing, [Claude via MCP](/integrations/claude) runs them conversationally, the other [integrations](/integrations) cover the middleware options, and [maps local lead to CRM](/use-cases/maps-local-lead-to-crm) walks the same write-it-yourself pattern end to end.
**Is a HubSpot app coming?** Not announced, and no CRM-native apps exist today. Build as though it is not coming. **Can I use the free HubSpot tier?** For paths 2 and 3, yes — private apps and the CRM API are not gated the way workflow custom code is. **Will this overwrite my reps' data?** Only if you tell it to. Write to `enriched_email`, review, then promote. That is the whole reason this page recommends a separate property. **How do I avoid enriching the same contact twice?** Branch on `enrichment_status` and `enriched_at`. HubSpot's own re-enrolment settings are the second guard. **Do you support HubSpot's data sync framework?** No. **Can I attribute credit spend to one workflow?** Yes, by issuing a separate API key per workflow. Named keys carry per-key usage attribution.
25 free credits, no card. Write the custom code action against ten stale contacts and look at what comes back before you enrol a list of four thousand. Endpoint detail: [email finder](/api/email-finder) and [company enrichment](/api/company-enrichment).