Playbooks · Playbook
Your product has an enrich button. Behind it, our endpoints on your API key, with per-key usage attribution so you can see which of your integrations spent what. Waterfall calls (email, phone) don't bill on a miss; enrichment and search calls bill on any 2xx.
Last updated September 22, 2026
Pattern: Your app → your server → api.richapi.ai with a named key per surface → your database. The key never reaches the browser, the cost model is yours to design, and every waterfall response carries an execution_log you can log or expose.
Credit math: A product doing 10,000 enrich-button presses a month: enrich_company at 1 credit per call × 10,000 = 10,000 credits if every press is a fresh call. Cache and that number drops to the count of first-time domains. Add email_finder at 5 credits per call only on presses that ask for a contact, where misses return billed:false and cost zero. Credits come from one prepaid pool, not per seat. Tiers on /pricing.
ROI math: Compare against building it: provider contracts, failover logic, a billing reconciliation nobody wants to own, and a support queue about stale data. The build is not the enrichment call, it is the eight weeks after the first provider changes its response shape.
Owned internally by: A backend engineer on your team. This is a server-side integration and it should stay one.
Best for: SaaS products (CRMs, ATSs, sales tools, agent platforms) that need enrichment inside their own UI and do not want to become a data company to get it.
// Your server. The key lives here and only here.
// A named key per surface gives you usage attribution later.
const enrich = async (linkedinCompanyUrl) => {
const res = await fetch("https://api.richapi.ai/api/v1/enrich_company", {
method: "POST",
headers: {
"x-api-key": process.env.RICHAPI_KEY_WEBAPP,
"content-type": "application/json",
},
body: JSON.stringify({ url: linkedinCompanyUrl }),
});
// Non-2xx never bills, on any endpoint. Surface it, don't swallow it.
if (!res.ok) throw new Error(`enrich_company ${res.status}`);
// enrich_company is NOT a waterfall endpoint: a 2xx bills even if
// the payload comes back thin. Cache the result either way.
return res.json();
};
Create one key per surface, not one key for the company.
Named keys give you per-key usage attribution, which is the only way you will ever answer 'which feature spent that'.
Put the key on your server.
Never in a browser bundle, a mobile binary, or a client-side agent your users can read.
Cache by input.
A company your product enriched on Tuesday does not need re-enriching on Wednesday, and enrich_company bills on every 2xx.
Decide your own unit of charge before you launch it.
Ours is credits; yours might be seats, rows, or included-in-plan. They do not have to match, and coupling them means your pricing page changes when ours does.
Log the execution_log on waterfall calls.
When a user asks why the email came back empty, that log is the answer, and reconstructing it later is impossible.
Handle the miss in your UI as a real state.
'No verified email found' is a legitimate outcome, not an error toast.
Your users pasted a domain into your product and expect a company to appear. You can build that, or you can call it. Building it means provider contracts, a failover chain, a cache, a reconciliation between what you were billed and what your users did, and ownership of the support ticket when a provider quietly changes a field name. This page is the other option: your UI, your database, your pricing, our endpoints behind them.
Server-side, always. Your frontend calls your backend, your backend calls `api.richapi.ai/api/v1/{endpoint}` with an `x-api-key` header, and the result lands in your database as your data. The key never touches a browser bundle, a mobile binary, or an agent your users can inspect. That's not a preference. A key in a client is a key your users can extract and spend, and there is no per-key spend ceiling to save you. The endpoints a platform usually wires up first: - `enrich_company`, 1 credit per call. Takes a **LinkedIn company page URL**, not a domain. If your UI collects domains, you need a resolution step first; `find_website_by_company_name` at 1 credit per call and `clean_domain` at 0.5 credits per call sit in that gap. - `enrich_profile`, 1 credit per call, LinkedIn profile URL. - `email_finder` at 5 credits per call and `email_verifier` at 2 credits per call, both waterfall. - `people_search`, per-result at 0.1 credits per result, so a list feature's cost scales with rows shown, not searches run.
You can create multiple named keys and see usage attributed per key. Use that: one key per surface, or per environment, or per major customer if that's how your account structure works. When finance asks which feature spent 40,000 credits last month, per-key usage is the answer. Be clear about the ceiling, because the adjacent features don't exist. There are no billed sub-accounts. There is no per-client credit budget you can set and have us enforce. There is no rate cap per key you can configure to protect yourself from your own runaway job. Named keys with per-key usage attribution is the honest version, and any spend ceiling your customers need is a ceiling you implement in your own code.
We are not going to tell you on a marketing page that you can resell this under your own brand. Whether you can, on what terms, with what attribution and what support path, is a commercial discussion with a human, not a checkbox in the dashboard and not a claim we make to close a signup. What you can do today without asking anyone: call the API from your backend, store the results as your own records, and present them in your UI however you like. What needs a conversation: reselling, co-branding, anything where our name and your contract meet.
The tempting shortcut is to expose credits directly, so your user spends a credit, you spend a credit, everyone can do the arithmetic. It falls over in three ways. Your pricing page now changes when ours does. Your users start optimising against our billing model instead of using your product. And the miss semantics leak: a `email_finder` miss costs you zero, so either you charge your user for nothing or you build a refund path for an outcome your UI already handled. Pick your own unit. Rows enriched, records refreshed, included-in-plan with a fair-use line. Buy credits in bulk against that, watch the ratio for a month, and adjust. The decoupling is the whole point of being the backend. The cheaper one to fix is having no cache at all. `enrich_company` bills on every 2xx. A user who clicks enrich three times on the same account bills three times unless you stop it.
Single region. No SOC 2 attestation: controls exist, the audit does not. No data-origin indemnification, which matters if your own customers ask you to sign something about data provenance. No SCIM, no CRM-native apps, no sending or sequencing. If your product needs any of those from a vendor contract, find out now rather than during your customer's security review.
**Can I let my users bring their own RichAPI key?** Nothing stops you, and it moves billing and rate behaviour onto them. It also means their key reaches your servers, so treat it as a credential you're now storing. **How do I show my users why an enrichment came back empty?** Log the `execution_log` on the waterfall calls and surface a summarised version. It lists the provider attempts and their statuses, so an empty result becomes an explanation rather than a shrug. **What happens to my costs if a call errors?** Non-2xx never bills, on any endpoint. A 2xx does bill outside the multi-provider waterfall endpoints, including a 2xx with a thin payload, so treat "returned successfully but useless" as a billable event in your own accounting. **Is there a partner or reseller programme?** Talk to us. It is not a self-serve thing and we are not going to pretend otherwise on a landing page. **Do I need a card to prototype?** No. 25 free credits on signup is enough to wire the button and see a real response shape before you commit anything.
/platform for the architecture view, the [use cases](/use-cases) hub for the other plays, [company enrichment](/api/company-enrichment) and [person enrichment](/api/person-enrichment) for the endpoints behind the button, [icp filter with ai enrich](/use-cases/icp-filter-with-ai-enrich) if your product also needs scoring, and [list build and verify](/use-cases/list-build-and-verify) for the list-side chain. Tiers on [pricing](/pricing). **25 free credits, no card.** Wire one endpoint into a staging build and see what the response actually contains.