Levels.fyi API

Get Levels.fyi compensation data by company, role and level

The Levels.fyi API returns tech salary and compensation data as clean JSON.

no credit card1,000 free credits · instant API key · live in 10 seconds
Missing a Levels.fyi endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
L
/levels-fyi/v1

5 active endpoints. Every call is 1 credit.

  • POST/levels-fyi/v1/company/salaries
  • POST/levels-fyi/v1/company/roles
  • POST/levels-fyi/v1/company/search
  • POST/levels-fyi/v1/role/companies
  • POST/levels-fyi/v1/submissions

What Levels.fyi endpoints does ReefAPI ship?

5 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

5 endpoints

company/salaries

1 cr

The flagship action.

required
company, role
optional
location

company/roles

1 cr

Resolve a company to its Levels.fyi profile (id, slug, website, employee count, HQ, vesting s…

required
company
optional

company/search

1 cr

Find companies on Levels.fyi by name.

required
query
optional
limit

role/companies

1 cr

For a given role/title, list every company that reports compensation data for it on Levels.fy…

required
role
optional
limit

submissions

1 cr

Paginated individual salary submissions for a company + role.

required
company, role
optional
location, page

Every parameter, every allowed value →

Levels.fyi API

3 of 5 endpoints, ready to run

View docs ↗

The whole compensation picture for one company and one role: the level ladder, per-level averages with their sample counts, and p10 through p90 for total comp, base, stock and bonus.

1 credit2 required · 1 optional
POST/levels-fyi/v1/company/salaries
idle
// Press "Try it" and this pane shows exactly what the
// live site returned this second — including an empty
// result, if that is the truth. No key, no account.

How the Levels.fyi API works

Levels.fyi is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 185 engines.

02
Call
POST /levels-fyi/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 credit per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Turn a title into a market, then a market into one company's ladder

Start with the role's coverage so you know which employers actually report data, then go company by company for the ladder and the percentiles.

01companies
POST/levels-fyi/v1/role/companies
{"role": "software-engineer", "limit": 2000}

Reported 1,431 companies for that role, with an overall median of 195,000 — and returned all 1,431. The reported count and the reachable count are the same number.

02salaries
POST/levels-fyi/v1/company/salaries
{"company": "<name>", "role": "software-engineer", "location": "new-york-city-area"}

Per-level averages with sample_count and sample_count_last_12_months, the percentage of the workforce at each level, and p10-p90 for total comp, base, stock and bonus separately.

A pay band you can defend, with the sample size attached to every number in it — and, if you want them, the individual anonymous datapoints underneath.

request
curl -X POST https://api.reefapi.com/levels-fyi/v1/company/salaries \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"company":"google","role":"software-engineer"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "levels-fyi",
    "endpoint": "company/salaries",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

Levels.fyi level ladders: what L4, SDE II, IC3 and ICT3 mean per company

Every company names its levels differently, and the level strings you get back are that company's own ladder rather than a normalized scale. The table below was measured on 2026-08-27 by calling company/salaries for the software-engineer role at each company with no location filter, which returns the United States figures. P50 is the median total compensation across all levels.

Company slugLevel ladder returnedMedian levelTotal-comp P50 (USD)
googleL3, L4, L5, L6, L7, also named SWE II, SWE III, Senior SWE, Staff SWEL4302,700
amazonSDE I, SDE II, SDE III, Principal SDE, Senior Principal SDE, Distinguished EngineerSDE II262,500
microsoftnumeric bands 59 to 80, some named: SDE 59-60, SDE II 61-62, Senior SDE 63-64, Principal SDE 65-66, Partner 68, Distinguished Engineer 70, Technical Fellow 80Senior SDE236,900
appleICT2, ICT3, ICT4, ICT5, ICT6, Distinguished Engineer, Senior Distinguished Engineer, Engineering FellowICT3271,500
nvidiaIC1 through IC8IC3268,000
stripeL1 through L7L2290,540
goldman-sachsAnalyst, Associate, Vice President, Managing Director, PartnerAssociate160,000

A company name is auto-slugified, so company 'Goldman Sachs' resolves to goldman-sachs. Each levels[] entry carries a titles array because a level usually has more than one name, for example ['L3','SWE II'] at Google and ['SDE','59'] at Microsoft, so match on any element rather than assuming titles[0].

How complete it is, how sure it is, and what the location parameter really does

Measured on 2026-08-28 against two companies, with and without a metro scope. Two of these lines go against us.

No account, and nothing here is anyone's identity

No Levels.fyi login is involved and there is no account of yours to limit. Just as importantly, the data itself is anonymous by construction: a submission comes back as a uuid with a level, a focus area, years of experience, an offer date and the money — no name, no employer email, no profile link. This is pay data, not people data.

⭐ The reported total is fully reachable

role/companies said company_count 1,431 for software engineer. Asking for 2,000 returned exactly 1,431 rows, in under a second. There is no hidden cap and no page you cannot get to — one of only two engines in this batch where the number the source reports is the number you can have.

Every average carries its sample size

The per-level block returns sample_count and, separately, sample_count_last_12_months — so you can tell a level whose average rests on 45 lifetime datapoints from one resting on 49 in the last year. Next to it, percent_workforce says how much of the company sits at that level. An average without a denominator is a rumour; none of these are missing theirs.

Four separate percentile ladders, not one

percentiles splits total_comp, base_salary, bonus and stock_grant, each with p10, p25, p50, p75 and p90. For one company's software engineers that meant a total-comp median of 290,540 sitting on a base median of 190,000, a stock median of 82,900 and a bonus median of 17,640 — the shape of the offer, not just its size.

location genuinely moves the numbers

The same company and role, measured nationally and then scoped to one metro, returned a total-comp median of 300,325 against 275,000, and the submission count behind the page fell from 88 to 71. The parameter is not decorative; if you quote a number without a metro, you are quoting a national blend.

🔴 The role coverage list is names only

Against us. role/companies returns 1,431 rows and every row is just a company name — no slug, no median, no employee count. To go from that list into company/salaries you re-slug the name yourself, and the auto-slugging is what will bite on companies whose display name and slug differ. Use company/search to resolve the awkward ones.

🔴 The submission rows have a null currency

Against us. Individual submissions carry base_salary, total_compensation, stock_grant_annual and bonus_annual as bare numbers with currency null, even though the parent response declares USD at the top level. Read the currency from the response, not from the row, or you will silently mix markets.

The company profile is a catalogue, not a roster

company/roles returned the company's Levels.fyi record — id, slug, website, employee count, HQ, vesting schedule — plus 105 job families it has data for, each with a description. A count of employees and a list of roles; never a list of people.

Dated at the datapoint level

Every submission carries an offer_date with a full timestamp, so "what has this company been paying in the last six months" is a filter over the rows rather than a question you have to ask the averages.

What people build with Levels.fyi

The jobs this data is most often used for.

5

endpoints

1

credit per call

01

Recruiting tools call company/salaries to benchmark an offer against a company's real pay bands.

02

Career products use role/companies to show which companies pay most for a given role.

03

Comp teams use the percentiles to calibrate salary ranges by level and location.

What Levels.fyi data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 185 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/levels-fyi/v1/company/salaries \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"company":"google","role":"software-engineer"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/levels-fyi/v1/company/salaries",
    headers={"x-api-key": REEF_KEY},
    json={
  "company": "google",
  "role": "software-engineer"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Levels.fyi.

Get a free key →
Which fields add up to total compensation?

base_salary plus stock_grant_annual plus bonus_annual, and it reconciles exactly. Google's median offer measured on 2026-08-27 returned base_salary 200000, stock_grant_annual 80000, bonus_annual 18000 and total_compensation 298000. An individual submission in the same response returned 122222 base, 22222 stock, 0 bonus and total_compensation 144444. Stock is the annualized grant value, not the four-year total, and commission appears as its own field in the per-level averages.

Are these numbers medians or individual salary submissions?

Both, in the same response. percentiles gives p10, p25, p50, p75 and p90 for total_comp, base_salary, bonus and stock_grant separately. median is one representative offer with its level, focus tag, location and years of experience. averages is one row per level with mean total_compensation, base_salary, stock_grant and bonus. sample_submissions carries individual anonymized datapoints, and the submissions action pages through more of them.

Why does sample_count say 39 for a level when the company has thousands of submissions?

Because two different counts sit side by side. In Google's software-engineer averages, level L3 returned sample_count 39 alongside sample_count_last_12_months 1106, while the median block returned sample_count 23928 for the role as a whole. Read sample_count_last_12_months for the recent volume behind a level's averages, and the median's sample_count for the size of the whole dataset.

How many individual submissions can I actually page through?

Fewer than the sample counts suggest. The submissions action returns 50 per page and reports its own totals: for google plus software-engineer on 2026-08-27 it returned total 104 across total_pages 3, while the same company and role reported 23,928 submissions behind the aggregates. The paginated feed is the recent public sample Levels.fyi publishes, not the full dataset, so use percentiles and averages for population figures and submissions for texture.

Which location slugs actually work?

Only the ones matching a real Levels.fyi page, and the naming is not guessable. Measured on 2026-08-27 for google plus software-engineer: new-york-city-area answered with location 'New York City' and a total-comp P50 of 298000, san-francisco-bay-area answered with P50 320000, and greater-seattle-area answered with P50 273000. bay-area, seattle-area, austin-area and london-area all returned error code NOT_FOUND. Omitting location gives the company-wide United States figures, which for Google was P50 302700.

What currency are the compensation numbers in?

US dollars on the US-scoped pages, reported as currency 'USD' at the top level and inside the median block. Individual rows are the exception: all 50 submissions in a measured page came back with currency null, so fall back to the response-level currency rather than reading it per row. No conversion is applied anywhere, so a non-US page reports whatever the source reports.

What does an individual salary submission contain?

uuid, level, title, focus_tag, years_of_experience, years_at_company, location, base_salary, stock_grant_annual, bonus_annual, total_compensation and offer_date. focus_tag is the specialization, with measured values including 'Full Stack', 'Testing (SDET)', 'Web Development (Front-End)' and 'Distributed Systems (Back-End)'. offer_date is a full ISO 8601 timestamp with milliseconds and offset, for example 2026-08-21T03:28:18.149+00:00, and it is the only ISO date in the response.

How do I find the right company and role slug?

company/search takes a partial name and returns matches with their slug and salaries URL. company/roles resolves a company to its profile, measured for Stripe as id 36, employee_count 8000, hq_city 'San Francisco' and company_type 'private', and returns the 105-entry job-family catalog you can query, starting software-engineer, product-designer, product-manager, data-scientist. Going the other way, role/companies lists every company reporting data for a role plus the country-wide median, which for software-engineer was 195,000.

What is the Levels.fyi API?

Levels.fyi API is a ReefAPI endpoint group for levels.fyi It returns live JSON through POST requests under /levels-fyi/v1.

Is the Levels.fyi API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Levels.fyi calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Levels.fyi login or account?

No login to Levels.fyi is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Levels.fyi data?

The page example is captured from a live company/salaries call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Levels.fyi API use?

Levels.fyi actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Levels.fyi from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call levels-fyi actions with the same key, credit pool and JSON envelope used by normal REST requests.

15 Jobs & Hiring APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Levels.fyi, you are one call away from the rest of the category — no second contract, no second integration.

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 184 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.