# get_pay

> Advertised pay, its trend, and market benchmarks

**Call:** `GET /v1/pay`  
**Price:** Uses credits (see each response's `X-Credits-Charged`)  
**Available:** soft launch  
**Contract:** https://api.gwix.ai/docs/reference

## What it's for

Advertised pay percentiles (p10-p90) by period, with optional change over time and market benchmarks.

## Use it when

- "What does a nurse earn in Denver?" (advertised pay)
- "How does our pay compare with the market?" - use `benchmark`.

## Inputs

| Name | In | Type | Required | Meaning |
|---|---|---|---|---|
| `company_id` | query | list of string |  | One or more brand-level company IDs (from the company lookup). Use only one of `company_id`, `parent_company_id` or `ticker`. |
| `parent_company_id` | query | string |  | Ultimate parent company ID; combines all its brands into one group. Uses current ownership for every period (`meta.ownership_basis`). |
| `ticker` | query | string |  | Stock ticker (`MAR`). Resolves to the listed company and is treated as `parent_company_id` (the whole corporate group, current ownership). Add `country` when the ticker is used in more than one country. |
| `split` | query | string: brand |  | With `parent_company_id`, return one row per brand instead of one group row. |
| `location_id` | query | list of string |  | One or more location IDs - country (`US`), state (`US-CO`) or metro (`mtr_…`). A city or postcode resolves to its metro through the location lookup. |
| `country` | query | string |  | ISO 3166-1 alpha-2 country code. |
| `industry_id` | query | list of string |  | One or more 4-digit NAICS industry groups. Statistics are built at 4 digits only, with no 2-, 3- or 6-digit rollups; to cover a wider sector, list its 4-digit codes or aggregate the results. |
| `role_id` | query | list of string |  | One or more standardized role IDs. Use one occupation filter. Role with a company, parent company or ticker is not pre-computed at launch (501); role with an industry is. |
| `job_family_id` | query | list of string |  | One or more job families (the broadest occupation level). |
| `sub_job_family_id` | query | list of string |  | One or more sub-job families (the level between job family and role). |
| `soc_id` | query | list of string |  | One or more US SOC 2018 detailed occupations (`soc_15-1252`), computed from each ad's SOC code. Geography and job level only; with a company, parent, ticker or industry filter 501. |
| `occupation_code` | query | list of string |  | One or more occupation codes as `<system>:<code>`: `soc_2018:15-1252`, `soc_2010:15-1132`, `onet_soc:15-1252.00`, `isco_08:2512`, `esco:2512.4` (short names `soc`, `soc2010`, `onet`, `isco` are accepted; a bare `15-1252` is SOC 2018). Each code resolves to the SOC 2018 detailed occupations it maps to (see `crosswalk`); the response has one row set per SOC occupation, each with `matched_from`, and `meta.occupation_codes` lists every mapping, including SOC occupations without data. A partial match covers only part of the SOC occupation; rows are never pooled across SOC occupations. Unknown code 422 `unknown_code`; a code whose SOC occupations have no ads 422 `no_data_for_code`. Same limits as `soc_id`.  |
| `job_level_id` | query | list of string |  | One or more job levels (seniority). |
| `interval` | query | string: week | month | quarter | year |  | Period type. Month = 4 weeks, quarter = 13, year = 52, anchored to complete weeks ending on or before the period's last day. |
| `start_period` | query | string |  | First period label, e.g. `2025-01`, `2025-Q2`, `2025`, `2025-W14`. |
| `end_period` | query | string |  |  |
| `compare` | query | string: previous | 12_month |  | Add the change against the previous period, or against the same period 52 weeks earlier. |
| `pay_unit` | query | string: annual | hourly |  | Annual pay, or hourly (annual ÷ 2,080). |
| `currency` | query | string: USD | local |  | `USD` (default) or `local`: each row in its country's own currency (ISO 4217 code in the row's `currency`). |
| `percentiles` | query | list of string: p10 | p25 | p50 | p75 | p90 |  | Percentiles to return. Default all five. |
| `benchmark` | query | list of string: national | industry | local | local_industry |  | Markets to compare the subject with. Requires an occupation filter (role, sub-job family, job family, SOC occupation or occupation code). SOC occupations take national and local only. |
| `benchmark_industry_id` | query | string |  | 4-digit NAICS industry group for the industry benchmark. Default is the subject's own 4-digit industry. |
| `cursor` | query | string |  | Opaque cursor from `paging.next_cursor`. |
| `limit` | query | integer |  | Rows per page, 1 to 1,000 (default 100). Requests needing more than 1,000 rows in total answer 501; narrow them. |

Headers: `Idempotency-Key`, `GWIX-Agent-Id`, `GWIX-On-Behalf-Of`.

## What comes back

`rows`, `meta`, `paging`.
If an input is ambiguous: `status: needs_disambiguation` with `candidates`, the `missing` input and a `retry_with` template (no charge).

## Rules

**Advertised pay.** Pay figures are advertised pay: what employers state in job ads. They are not what any employer actually pays, and not official statistics.

**Pay units.** Pay is annual by default; hourly = annual / 2,080. Statistics are computed in each country's own currency and returned in USD at the period's average exchange rate (`fx_rate`, units per USD), or in the country's currency with `currency=local` (the row's `currency` names it). Record pay is in USD. The rates used are published by `list_fx_rates`.

**Minimum sample sizes.** A pay percentile is shown only when enough ads state pay: p50 needs 10, p25 and p75 need 20, p10 and p90 need 50. Below that the value is null and listed in `suppressed` with reason `below_minimum`.

**Periods.** Periods are whole Monday-Sunday weeks. A month is 4 weeks, a quarter 13, a year 52, anchored to complete weeks ending on or before the period's last day. There are no partial periods; the current week is never included until it is complete. Ask for periods with `interval` plus `start_period` and `end_period` labels (custom date ranges are not available at launch).

**Zeros and coverage.** `coverage_status: covered` means GWIX sources were watching, so a zero means no ads were observed. `not_covered` means GWIX cannot say; values are null. Periods and named values are always returned, even when zero; unnamed zero rows are omitted and counted in `meta.zero_rows_omitted`.

**Geography.** Statistics are built at metro level. Location filters work at metro, state and country at launch; a city or postcode resolves to its metro. Every row is specific to one country.

**Company groups and ownership.** Company groups (`parent_company_id`, `ticker`) use current ownership for every period (`meta.ownership_basis: current`). A brand acquired last year is counted in its current parent's history.

**IDs, not plain text.** Statistics take IDs. Resolve names to IDs first with `lookup` (company, ticker, place, city, postcode, job family, sub-job family) or send occupation codes (`occupation_code`). Plain-text filters (`title`, `company`, `location`, `job_family`) are not available at launch and answer 501 with a `retry_with` lookup link.

**Request size.** A request answers up to 1,000 rows and 200 filter combinations inline; larger requests answer 501 `job_required` - narrow the filters or periods. Asynchronous jobs come later.

**Provenance and reproducibility.** Every response carries `meta.provenance` (the data release and its last complete week) and a ready-made `meta.citation`. Statistics come from the live weekly release; each response names it.

## Notes

- `benchmark` compares the subject with the same occupation (role, sub-job family, job family or SOC occupation) in the national, industry, local or local-industry market; it requires an occupation filter. SOC occupations take national and local only.
- The industry benchmark uses the subject's 4-digit NAICS industry group, with no step-down to wider sectors; when counts are too low its percentiles are suppressed.
- Industry filters are 4-digit NAICS only; for a wider sector, list its 4-digit codes or aggregate the results.
- Role with a company, parent company or ticker is not pre-computed at launch (501); use sub-job family or job family with a company. Role with an industry is pre-computed.
- With `compare` and `benchmark` together, each market block carries `market_change_pct` and `growth_gap_pp`.
- Group percentiles pool every brand's ads.
- Weekly figures (`interval=week`) are served for occupations, single companies (also brand by brand with `split=brand`) and industries on their own; for a parent company or ticker, a company or industry combined with an occupation, or industry benchmarks, use month, quarter or year (weekly returns 501).
- Use `currency=local` for pay trends within a country (no exchange-rate effects) and USD to compare countries; always state the currency shown in the row.
- Occupation codes: send `occupation_code=isco_08:2512` (also `soc_2018`, `soc_2010`, `onet_soc`, `esco`) or `soc_id`; you get one row set per SOC 2018 detailed occupation the code maps to, each with `matched_from`. A `partial` match covers only part of the SOC occupation - say so. Never add SOC rows together for pay. SOC occupations are by geography and job level only.

## How to word results

- Cite GWIX using `meta.citation`.
- Say "advertised pay" or "pay in job ads", never "salary paid" or "what X pays".
- State the currency of every pay figure (the row's `currency`).
- Say "ads first posted", not "jobs" or "hires" or "openings filled".
- Report suppressed percentiles as "not enough ads stating pay to report", not as zero.
- Report zeros with `covered` as "no ads observed in GWIX sources", not "no jobs exist".
- State the level actually used (e.g. metro, 4-digit NAICS) from `meta`.
- For company groups, say figures use current ownership.
- Never: present figures as official statistics or as an employer's actual pay.
- Never: name a data vendor; name datasets as they appear in `meta.provenance`.

## When it doesn't work

| Status | What to do |
|---|---|
| 202 | Still running: you have a job. Poll `get_job` or wait for a webhook. |
| 400 | Fix the request; `invalid_params` names each bad parameter. |
| 401 | Send a valid API key (`Authorization: Bearer ...`). |
| 402 | Not enough credits. The body lists packs and plans that would cover it. |
| 403 | Not allowed for this key or tier, a cap is reached, or the agent is unidentified; read `type` and `detail`. |
| 409 | Idempotency-Key reused with a different request, or the action conflicts with the current state. |
| 422 | Parameters conflict (e.g. two company filters) or use a reserved feature. |
| 429 | Rate or concurrency limit. Wait `Retry-After` seconds. |
| 503 | Temporarily unavailable; see `get_status`. |

## Next steps

[`get_postings`](/context/get_postings) · [`list_fx_rates`](/context/list_fx_rates)

## Example response

```json
{
  "rows": [
    {
      "period_label": "2026-Q3",
      "period_start": "2026-06-29",
      "period_end": "2026-09-27",
      "country": "US",
      "location": {
        "id": "mtr_denver_aurora_co",
        "name": "Denver-Aurora-Lakewood, CO",
        "geo_level": "metro"
      },
      "role": {
        "id": "rol_29-1141.00",
        "name": "Registered Nurse"
      },
      "coverage_status": "covered",
      "pay_unit": "annual",
      "currency": "USD",
      "fx_rate": 1,
      "ads_with_pay": 412,
      "percentiles": {
        "p10": 71500,
        "p25": 78200,
        "p50": 86400,
        "p75": 95100,
        "p90": 104800
      },
      "suppressed": [],
      "market": [
        {
          "scope": "national",
          "ads_with_pay": 18240,
          "percentiles": {
            "p10": 66800,
            "p25": 74100,
            "p50": 82900,
            "p75": 93600,
            "p90": 106200
          },
          "gap_pct": {
            "p10": 7.0,
            "p25": 5.5,
            "p50": 4.2,
            "p75": 1.6,
            "p90": -1.3
          }
        }
      ]
    }
  ],
  "meta": {
    "request_id": "gwx_req_9d2p4q",
    "provenance": {
      "datasets": [
        {
          "id": "us-postings-core",
          "last_complete_week": "2026-10-25"
        }
      ],
      "data_release": "2026-W43",
      "methods": {
        "pay_consolidation": "2.3"
      },
      "taxonomy_version": "utb-1.0",
      "computed_at": "2026-10-28T14:05:51Z"
    },
    "citation": {
      "text": "GWIX advertised pay, Registered Nurses, Denver metro, 2026-Q3, release 2026-W43, retrieved 28 Oct 2026 (gwx_req_9d2p4q)",
      "url": "https://api.gwix.ai/v1/requests/gwx_req_9d2p4q"
    }
  },
  "paging": {
    "next_cursor": null
  }
}
```
