Data catalog / Proxycurl Migration

Proxycurl Person Profile Endpoint replacement

Proxycurl's Person Profile Endpoint took a LinkedIn profile URL and returned a person record. POST /enrich_profile takes the same input and returns the same kind of record under different field names. The URL swap is ten minutes; re-mapping the fields is the afternoon. This page covers both, and is clear that a 2xx bills even when the record comes back thin.

In short: Proxycurl's Person Profile Endpoint accepted a LinkedIn profile URL and returned a person record. It is offline because Proxycurl shut down. The RichAPI replacement is POST https://api.richapi.ai/api/v1/enrich_profile. Authentication uses an x-api-key header, not a Bearer token. The request body is JSON with a single required field, url, holding a LinkedIn profile URL. The response is a flat JSON object whose fields include firstname, lastname, headline, summary, location, profilePicture, currentCompany, currentTitle, connectionCount, followerCount, linkedinUrl, and the arrays experience, education, skills, certifications and languages. Field names differ from Proxycurl's, so a migration requires re-mapping the response. Pricing is a flat credits_per_call. The endpoint is not a waterfall: any 2xx response is billed, including a response that contains little or no data. Non-2xx responses are never billed. New accounts get 100 free credits with no credit card at https://app.richapi.ai.

Last updated November 4, 2026

Your Person Profile calls are returning errors. Here is the one that works.

Proxycurl is gone, so every GET against its Person Profile Endpoint now fails and your enrichment jobs are writing nulls. The replacement is POST /enrich_profile. It takes the same thing yours already has, a LinkedIn profile URL, so nothing upstream in your pipeline has to change.

Get 100 free credits — no card

Of the four Proxycurl endpoints people are migrating off, this is the cleanest. Same input type, same kind of output, different field names. Budget the afternoon for the field names, not for the call.

The before and after

# Before (Proxycurl) — dead
# GET https://nubela.co/proxycurl/api/v2/linkedin?url=<profile-url>
#   -H "Authorization: Bearer $PROXYCURL_KEY"
#   Proxycurl's public docs are offline. Confirm paths against your own archived client code before you migrate.

# After (RichAPI)
curl -X POST https://api.richapi.ai/api/v1/enrich_profile \
  -H "x-api-key: $RICHAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.linkedin.com/in/example/"}'

Three mechanical changes: GET with a query string becomes POST with a JSON body, Authorization: Bearer becomes x-api-key, and the parameter is url. There is no OAuth step and no token exchange.

The field mapping is the actual work

Both APIs return a person, but they disagree on what to call the parts of one. RichAPI's response is flat JSON with these fields:

Field Type What it holds
firstname string Given name
lastname string Family name
headline string The line under the name on the profile
summary string The About section
location string Location as the profile states it
currentCompany string Employer on the current role
currentTitle string Title on the current role
profilePicture string Image URL
connectionCount number Connections
followerCount number Followers
linkedinUrl string Canonical profile URL
experience array Role history
education array Schools
skills array Listed skills
certifications array Listed certifications
languages array Listed languages

Two differences will bite you if you skip them. RichAPI splits the name into firstname and lastname where Proxycurl carried a single full-name field, so any code doing record.full_name.split() needs deleting rather than porting. And the arrays are the part your adapter should treat as untrusted: if you were reading a nested key off a Proxycurl experience entry, check the live shape before you write the mapping.

The authority is https://api.richapi.ai/api/v1/openapi.json. Read fields off that, not off this table, because this table is a page and that is the spec.

Migrate in four steps

1. Get a key. Sign up at app.richapi.ai, 100 free credits, no card.

2. Change the call. Swap host, method and auth header as shown above. If your Proxycurl client was a thin wrapper, this is a single function.

3. Write the mapping in one place. Put a from_richapi(payload) function between the API and the rest of your code, returning whatever internal person object you already use. Everything downstream then keeps compiling untouched, and when the response gains a field you edit one function.

4. Replay records you already know. Take twenty profiles where you still have the old Proxycurl output in your database, run them through the new call, and diff. That comparison tells you your real coverage on your real accounts, which no vendor page can.

Calling it from an agent works too. The hosted MCP server exposes enrich_profile as a tool in Claude, Cursor and VS Code, which is a fast way to eyeball the response shape before you write the adapter.

What a call costs, and when you pay

1 credit per call, flat. Credits are prepaid with no seats, no subscription and no contract; the per-credit rate is tiered by package size, so read yours from the pricing page.

This endpoint is not a waterfall endpoints, and every 2xx is billed, including one that comes back thin. We do have endpoints where a miss costs zero credits, email finder and email verifier among them, and this is not one of them. If you are re-enriching a stale list of 50,000 profile URLs, budget for 50,000 charges and not for the subset that resolves. 4xx and 5xx responses cost nothing on any endpoint.

The receipt on the person profile endpoint

A thin record here raises one question. Was there nothing to find, or did the routing go wrong? execution_log answers it, listing the sources tried, the order, and what each one returned, which is the difference between a data problem and a routing problem. Proxycurl gave you a status code and left you guessing.

What people use the person profile endpoint for

Restarting a stalled CRM sync. The nightly job that hydrated contact records off LinkedIn URLs has been failing since the shutdown. Point it here, map the fields once, and the backlog drains on the next run.

Candidate screening inside an ATS. experience and education are what the screen reads, and the recruiter is looking at the record while the call happens rather than overnight.

An agent that researches a person mid-conversation. Through MCP the profile lookup is a tool call, so the agent pulls a record when it decides it needs one instead of you pre-enriching a list you hope it will use.

The person profile endpoint FAQ

Is this a drop-in replacement?
The request is close to one. The response is not, because the field names differ. Plan for a mapping layer, and do not deploy a find-and-replace on a Friday.

Can I pass a vanity URL, or a URL with tracking parameters on it?
Send the clean linkedin.com/in/<slug>/ form.

Do I get charged when the profile comes back nearly empty?
Yes. A 2xx is billed on this endpoint whatever it contains. Zero-cost misses apply to the waterfall endpoints, not to this one.

What about the profiles I used to resolve from an email address?
That is a two-call chain now. See the Person Lookup migration.

How fresh is the record?
It is retrieved at request time rather than read out of a snapshot we refresh on a schedule. We do not sell an index size, because people change jobs and an index does not.

Can I call this from Claude or Cursor?
Yes, through the hosted MCP server, no install. The tool list updates itself as endpoints change.

Do I need a credit card to test the migration?
No. 100 free credits on signup.

Related

Try the person profile endpoint: 100 free credits, no card

Run twenty profiles you already have answers for and diff them against your old output. Get 100 free credits

See it in a workflow

Playbooks

Real patterns, recipes, and prompts other builders run on RichAPI

Start free with 100 credits

Developer Docs

Auth, request shape, and error handling

See Documentation

FAQ

Frequently asked questions

Proxycurl's Person Profile Endpoint took a LinkedIn profile URL and returned a person record. POST /enrich_profile takes the same input and returns the same kind of record under different field names. The URL swap is ten minutes; re-mapping the fields is the afternoon. This page covers both, and is clear that a 2xx bills even when the record comes back thin.
Every endpoint is billed from the same credit pool, at the published rate on /pricing — never a separate contract per endpoint.
Yes — the same endpoint is reachable from an MCP client (Claude, ChatGPT, Cursor, Windsurf) using the same key and credit pool. See /mcp.

Related data