# Migrating from Proxycurl to Veezee

## Background

Proxycurl shut down its LinkedIn API in July 2025 to comply with a legal settlement, after LinkedIn sued its operator in January 2025 (announcement: nubela.co/blog/goodbye-proxycurl/; docket: LinkedIn Corp. v. Nubela Pte. Ltd., 3:25-cv-00828, N.D. Cal.). Production integrations built on it need a replacement.

This guide maps each historical Proxycurl endpoint to the closest Veezee equivalent and says plainly where none exists. Proxycurl route details come from the archived public docs (web.archive.org snapshot of nubela.co/proxycurl/docs, June 2025) and the official public Postman collection; nothing here is guessed.

Veezee is an agent-first social data API (LinkedIn, Reddit, and X); its LinkedIn surface is six tools over MCP (`https://mcp.veezee.io/linkedin`) and REST (`https://api.veezee.io`, contract at [/openapi.json](/openapi.json)), credit-priced. No signup: the agent mints its own free key in one call.

## Endpoint map

| Proxycurl (historical) | Veezee | Migration notes |
| --- | --- | --- |
| Person Profile `GET /api/v2/linkedin` | `linkedin_get_profile` `GET /v1/linkedin/profiles` | Proxycurl took `linkedin_profile_url` plus include/exclude extras. Veezee takes `identifier` (URL, slug, or URN) and `sections` (about, experience, education, skills). Response fields are not drop-in compatible; plan a mapping pass. |
| Company Profile `GET /api/linkedin/company` | `linkedin_get_company` `GET /v1/linkedin/companies` | `identifier` accepts a company URL, slug, numeric id, or website domain. |
| Company Lookup `GET /api/linkedin/company/resolve` | `linkedin_get_company` with the domain | Pass the website domain as `identifier`; Veezee resolves it and verifies the result against the company's own website. The first lookup of a new domain adds 4 credits; known domains settle at the base price. An unverifiable domain returns INVALID_INPUT with the closest matches, never a guessed company. |
| Person Search `GET /api/v2/search/person/` | `linkedin_search_people` `GET /v1/linkedin/search` | Proxycurl used Boolean query-string filters. Veezee uses typed params: keywords, first_name, last_name, title, school, current_company, past_company. Matching behavior differs; re-test your queries. |
| Company Search `GET /api/v2/search/company` | no standalone equivalent | Veezee has no company-search tool in v1. With a domain in hand use linkedin_get_company directly; inside people searches the company filters accept plain names and resolve internally. |
| Employee Listing `GET /api/linkedin/company/employees/` | `linkedin_search_people` with current_company | A search, not an exhaustive roster; enrich selected results with linkedin_get_profile. |
| Employee Search `GET /api/linkedin/company/employee/search/` | `linkedin_search_people` | Replace `keyword_regex`/`country` with title and keyword filters; regex matching is not supported. |
| Person Lookup `GET /api/linkedin/profile/resolve` | `linkedin_search_people`, then `linkedin_get_profile` | No one-result resolver; search, pick the right hit, enrich it. |
| Role Lookup `GET /api/find/company/role/` | `linkedin_search_people` with title + current_company | Proxycurl returned a single closest match; Veezee returns candidates for you to pick from. |
| Employee Count `GET /api/linkedin/company/employees/count` | `linkedin_get_company` employee_count field | No current/past split and no historical at_date query. |
| Person posts (served as `activities`/`articles` fields of the profile response; no standalone endpoint existed) | `linkedin_get_posts` `GET /v1/linkedin/posts` | One dedicated tool for person or company posts, cursor-paginated. |
| Company `updates` field of the company response | `linkedin_get_posts` with the company identifier | |
| Credit Balance `GET /api/credit-balance` | `get_usage` `GET /v1/usage` | Free and exempt from the per-minute rate limit. get_usage needs a paid key: a free key's response already shows its own cost, with no account to check. |
| Contact API (personal email, work email, phone, reverse email, reverse phone, disposable-email check) | none | Veezee serves no contact-detail lookups, and linkedin_get_profile does not return emails or phone numbers. |
| Jobs API, School API, student listings, profile-picture endpoints | none | Outside Veezee's v1 scope. |

## What you must rework, honestly

- Contact data (emails, phone numbers) has no Veezee replacement; if you need it, integrate a separate purpose-built service.
- Exhaustive employee rosters and historical headcounts are not served.
- Response schemas differ everywhere; treat [/openapi.json](/openapi.json) as the source of truth and budget one mapping pass per endpoint.
- Every metered REST call needs an `Idempotency-Key` header, GET included, once you're calling with a paid key. Reuse the same key only to retry the identical call. Free-tier calls need no Idempotency-Key.

## Five-minute start

No signup: mint a free key and call it.

```
curl -s -X POST https://api.veezee.io/v1/keys/mint | jq -r .key > ~/.veezee/key
curl "https://api.veezee.io/v1/linkedin/profiles?identifier=williamhgates&sections=experience,education" \
  -H "Authorization: Bearer $(cat ~/.veezee/key)"
```

That runs under a shared free-key budget of 200 credits per IP per day. Past that, buy a key at [/upgrade](/upgrade): pay, and checkout credits the same key. Then send it on every call:

```
curl "https://api.veezee.io/v1/linkedin/profiles?identifier=williamhgates&sections=experience,education" \
  -H "Authorization: Bearer $VEEZEE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

`identifier` also accepts a full LinkedIn URL. Check spend anytime with `GET /v1/usage` (free, needs a key).

## Pricing model

Both products price in credits, but the units are unrelated; never convert a balance one to one. Proxycurl varied cost by endpoint, results returned, and optional enrichment flags (archived docs).

Veezee prices per call: 4 credits per profile (each section beyond the included two adds 2 credits), 10 credits per search page, 4 credits per company (4 credits more on the first lookup of a new domain), 4 credits per posts page, 2 credits per URL resolution.

Realtime fetches add 2 credits, refunded automatically on cached fallback. Full table and worked examples: [/pricing](/pricing).

## Sources

- Shutdown announcement: nubela.co/blog/goodbye-proxycurl/ (2025-07-04)
- Lawsuit docket: LinkedIn Corporation v. Nubela Pte. Ltd. et al, 3:25-cv-00828, N.D. Cal., filed 2025-01-24
- Archived Proxycurl API docs: web.archive.org/web/20250601194455/https://nubela.co/proxycurl/docs
- Archived Search API page: web.archive.org/web/20250706022442/https://nubela.co/proxycurl/search-api.html
- Official Postman collection: postman.com/proxycurl-team/proxycurl/documentation/mwz67fs/proxycurl
