Getting Started
Resolve a company once, then fan out across all four employer-data surfaces with the same id.
1. Get your API key
Create an account and generate a FetchLayer API key from your dashboard. There is no Glassdoor account, partner programme, or employer login involved.
Create free account →2. Turn a company name into an id
Every other endpoint takes a company handle. Search once, keep the employerId.
curl -X POST https://api.fetchlayer.dev/glassdoor/search-companies \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"query":"Stripe","limit":5}'Tip
/resolve-url first — it reports which kind of page the URL names and pulls the company id straight out of it, and it does not consume a credit. 3. Fan out across the four surfaces
The same id reads the ratings profile, the employee reviews, the reported pay and the candidate interview reports. Only the reviews and the interview reports page.
# Employer brand as numbers — one call, no paging
curl -X POST https://api.fetchlayer.dev/glassdoor/company-profile \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"company":"671932"}'
# The written reviews behind those numbers
curl -X POST https://api.fetchlayer.dev/glassdoor/company-reviews \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"company":"671932","pages":3,"limit":60,"sortBy":"date"}'Read the notes array
notes — plain-language strings reporting a walk that stopped short, a listing with more pages, or an upstream limit that was hit. A capped result is still a well-formed 200, so notes is the only place it says so. 4. Know the two ceilings
Salaries are page one only. /company-salaries accepts no pages and no cursor, because the upstream listing is not routed past its first page. Raising limit returns more of that page and nothing beyond it.
Sorting is local. sortBy on the reviews endpoint orders the reviews that request collected — the window your pages and limit defined — not the company's entire review history. To get the genuinely newest reviews at a large employer, widen the walk rather than trusting the sort.
Error responses
Every error, on every route, is JSON in one shape: error (what went wrong, in words), status, code, retryable and requestId, which also comes as the X-Request-Id header. Branch on code and retryable rather than on the text; on a 5xx the text is generic. Quote requestId when reporting a problem.
{
"error": "Missing required parameter: url",
"status": 400,
"missing": ["url"],
"code": "invalid_input",
"retryable": false,
"requestId": "922874e3-c0d0-40d8-8866-d198af132420"
}| code | Status | Retryable | Meaning |
|---|---|---|---|
| invalid_input | 400 | no | The request needs fixing; error names the field. A missing required parameter also lists it in missing. |
| unauthorized | 401 | no | The API key is missing or not valid. |
| insufficient_credits | 402 | no | Nothing left to spend: no credits, a used-up free trial, or a monthly allowance and credit balance both spent. error says which. Waiting does not help; topping up does. |
| forbidden | 403 | no | This key or account is not allowed this request. |
| not_found | 404 | no | What the request names does not exist or is not public. |
| expired | 410 | no | What the request refers to is no longer available; ask for it afresh. |
| quota_exceeded | 429 | no | A request-rate limit was reached; error says which. Slow down before sending more. |
| cancelled | 499 | no | The caller closed or cancelled the request before it finished. The work was stopped and nothing was charged. |
| time_limit | 503 | yes | Your timeoutMs ran out before there was anything to return; ask again, or allow more time. |
| temporarily_unavailable | 503 | yes | Not available right now; ask again shortly. |
| store_unreachable | 503 | yes | Store routes (Shopify, WooCommerce): the store itself can’t be reached right now — it may be offline. Ask again later. Where a store route doesn’t say so yet, an offline store is temporarily_unavailable. |
| upstream_error | 502 | yes | The source answered in a way that could not be used; ask again later. |
| internal_error | 500 | yes | Something failed on our side; ask again later, and quote requestId if it persists. |
| tool_error | — | no | MCP only: a tool call failed in a way no other code describes; error says what. |
More codes may be added; treat one you do not recognise by its retryable flag. Over MCP, a tool error carries the same fields in structuredContent, and as a JSON text block beside the message.