Integrations · Salesforce

Salesforce Enrichment API — Apex Callout, Flow or Middleware

We have no Salesforce app and no AppExchange listing. Nothing to install. You reach RichAPI from Salesforce through an Apex callout on a Named Credential, an HTTP Callout in Flow, or middleware sitting between the two, and you write the result to the object yourself.

Start free — 25 credits

Last updated September 22, 2026

Connect it.

  1. 01

    Create a RichAPI account at app.richapi.ai/signup and copy your API key.

    25 free credits, no card.

  2. 02

    In Salesforce Setup, create an External Credential (Custom authentication protocol) holding the key, and a Named Credential pointing at https://api.richapi.ai. This keeps the key out of Apex source and out of anyone's git history.

  3. 03

    Grant the External Credential principal to the permission set of whoever will run the enrichment.

  4. 04

    Pick a path: Apex for anything asynchronous or bulk, Flow HTTP Callout for a single record on a button or a record-triggered event, middleware if you would rather not deploy Apex at all.

  5. 05

    Write the fields to Lead, Contact or Account yourself.

    We return JSON; mapping it onto your object model is yours, and it is the part that would be wrong if we shipped an app anyway.

What you can ask for.

Copy, paste, edit the brackets, run.

Record-triggered Flow on Lead create: call email_finder on the name and website, write Email and a Source field, and skip the assignment rule if it misses.
Queueable Apex over an Account list view: enrich_company on each, update Industry and NumberOfEmployees where they are blank.
Quick Action on Contact: find_linkedin_url_by_email, then enrich_profile, then write the headline and seniority into custom fields.
Nightly Batch Apex: re-verify every Lead email older than 90 days and flag the invalid ones before the next campaign.
Middleware route: new Lead webhook → phone_finder → PATCH the record back through the Salesforce REST API.

Why it matters

Every enrichment vendor with a managed package is also a vendor whose field mapping you will spend a week fighting. Doing it as a callout means you decide which object, which field, and what happens on a miss. A miss on our waterfall endpoints costs you nothing, so the nightly re-verify job is affordable to run.

Salesforce enrichment: there is no app to install

We have no AppExchange listing, no managed package, and no Salesforce-native app. If you came here to click Install, stop reading and go look at a vendor who has one. That is a real reason to pick someone else and we would rather you find out in the first paragraph than after a sales call. What we have is an HTTP API that Salesforce can call three different ways. All three work. None of them involve a package upgrade breaking your sandbox.

Store the key properly first

Setup → Named Credentials. Create an **External Credential** using the Custom authentication protocol, with a named principal carrying a parameter for the API key. Then a **Named Credential** pointing at `https://api.richapi.ai`, referencing that external credential, with `x-api-key` set from the principal parameter. Then grant the principal on a permission set. Do this before you write anything, because the alternative is an API key in an Apex class in a repo, and that key is now in every sandbox refresh anyone has ever taken.

Path one: Apex

This is the path for anything bulk or asynchronous, which is most of it. ```apex public class RichApiEnrich implements Queueable, Database.AllowsCallouts { private List<Id> leadIds; public RichApiEnrich(List<Id> ids) { this.leadIds = ids; } public void execute(QueueableContext ctx) { List<Lead> toUpdate = new List<Lead>(); for (Lead l : [SELECT Id, Name, Website FROM Lead WHERE Id IN :leadIds]) { HttpRequest req = new HttpRequest(); req.setEndpoint('callout:RichAPI/api/v1/email_finder'); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); req.setBody(JSON.serialize(new Map<String, Object>{ 'full_name' => l.Name, 'company_domain' => l.Website })); HttpResponse res = new Http().send(req); Map<String, Object> body = (Map<String, Object>) JSON.deserializeUntyped(res.getBody()); if (body.get('success') == true) { Map<String, Object> d = (Map<String, Object>) body.get('data'); toUpdate.add(new Lead(Id = l.Id, Email = (String) d.get('email'))); } } if (!toUpdate.isEmpty()) update toUpdate; } } ``` Two Salesforce constraints shape this and you cannot design around them: - **No callouts after DML in the same transaction.** Enrich, collect, then update once at the end. The loop above does that on purpose. - **Callouts per transaction are capped.** Chunk the list and chain Queueables, or use Batch Apex with a small scope size. A list view button that tries to enrich a thousand leads synchronously will fail, and it will fail in a way that looks like our API broke. Check `body.get('success')` and not the status code. A waterfall miss returns **200** with `"success": false` and `"billed": false`. If you branch on `res.getStatusCode() == 200` you will write blank emails onto good leads.

Path two: Flow

For one record at a time, on a button or a record-triggered Flow, the **HTTP Callout** action in Flow Builder works without a line of Apex. Point it at the Named Credential, give it a sample response so Flow can build the data structure, and branch on `success` in a Decision element. Flow can also generate the invocable action from an OpenAPI spec via External Services. Ours is live at `api.richapi.ai/api/v1/openapi.json`. The import is fussy about schema features and we have not certified it. Flow is the wrong tool for volume. One record, on demand, is what it is good at.

Path three: middleware

If you do not want Apex in your org at all, put [n8n](/integrations/n8n) or [Make](/integrations/make) in the middle. New Lead fires a webhook, the middleware calls us, and its Salesforce node writes the record back. You trade a deployment for a subscription and a second place where things can break.

Cost, and why the re-verify job is affordable

| Endpoint | Cost | | --- | --- | | `email_finder` | `5 credits` | | `email_verifier` | `2 credits` | | `phone_finder` | `25 credits` | | `enrich_company` / `enrich_profile` | `1 credit` | | `find_linkedin_url_by_email` | `4 credits` | Full price only on results, scoped: `email_finder`, `email_verifier` and `phone_finder` cost zero when the providers all come back empty. The rest bill on a successful 2xx even if the payload is thin. Nothing non-2xx ever bills. Tiers on [/pricing](/pricing). That scoping is what makes a nightly hygiene job sane. Running `email_verifier` across a stale database costs you the hits and not the dead rows. Store `execution_log` on the record next to the enriched fields. Waterfall calls return one entry per provider attempt with a status, and a year later that is the only evidence of why a field is blank. Write it to a long text field on the record and your "why is this lead missing an email" question becomes answerable a month later.

Where we stop with Salesforce

No app, no field mapping, no sync, no sending, no prospecting UI, no SCIM. We return JSON. You own the object model, and honestly you should. Nobody's managed package has ever guessed your custom fields correctly. Related: [company enrichment API](/api/company-enrichment), [email verifier API](/api/email-verifier), [HubSpot](/integrations/hubspot) for the other CRM with the same answer, [verify before sequence push](/use-cases/verify-before-sequence-push), and the full [integrations index](/integrations).

Salesforce FAQ

**Is RichAPI on the AppExchange?** No. No listing, no package, no plans we can promise on a marketing page. **Can I install this in a sandbox and test it?** Yes. Named Credential plus the Apex above, on the 25 free credits. **Does it write to Salesforce itself?** No. We answer lookups. Every write is yours, which is also why there is no sync to break. **What about Salesforce's callout limits?** They are Salesforce platform limits, not ours. Asynchronous Apex with chunking is the standard answer; check the current numbers in Salesforce's own limits documentation. **Does `enrich_company` take a website?** No, a LinkedIn company URL. Resolve the domain first if that is all the Account has. **Can I give each business unit its own key?** Named keys with per-key usage attribution, yes. Not per-key credit budgets, because the pool is shared.

Start with Salesforce

25 free credits, no card. Build the Named Credential and run one Queueable against ten leads before you commit to anything.

Frequently asked.

Does Salesforce see my RichAPI key?
No — Salesforce Enrichment API — Apex Callout, Flow or Middleware authenticates through the connection you set up, using the same key and credit pool as the REST API. Revoking access from your RichAPI dashboard disconnects it immediately.
Does this cost more than using the REST API directly?
No — MCP and REST share the same credit pool and the same published endpoint rates. There's no separate MCP surcharge.

More integrations

Try it with 25 free credits.