> ## Documentation Index
> Fetch the complete documentation index at: https://kardow.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Salaries

> Aggregated salary statistics for your board's live jobs

One call returns your board's whole salary picture: an overall distribution plus breakdowns by category, job type, and location. Use it for salary widgets, market reports, or "what does this role pay" landing page copy, without pulling every job and computing the numbers yourself.

```bash cURL theme={null}
curl --url "https://api.kardow.com/salaries" \
  --header "x-api-key: your-api-key-here"
```

```json theme={null}
{
  "data": {
    "currency": "USD",
    "total_active_jobs": 240,
    "salaried_jobs": 85,
    "excluded_other_currency": 2,
    "excluded_implausible": 1,
    "periods": { "yearly": 60, "hourly": 25 },
    "overall": { "count": 85, "min": 31200, "max": 250000, "avg": 88000, "p25": 62000, "median": 85000, "p75": 110000 },
    "by_category": [ { "id": "uuid", "name": "Nursing", "slug": "nursing", "count": 24, "min": 52000, "max": 140000, "avg": 89000, "p25": 71000, "median": 86000, "p75": 104000 } ],
    "by_job_type": [ { "value": "full-time", "count": 61, "min": 31200, "max": 250000, "avg": 91000, "p25": 65000, "median": 88000, "p75": 112000 } ],
    "by_location": [ { "value": "Austin, TX", "count": 12, "min": 45000, "max": 160000, "avg": 92000, "p25": 68000, "median": 90000, "p75": 115000 } ]
  }
}
```

## How the numbers are computed

* **Live jobs only.** Active, unexpired jobs that publish `salary_min` or `salary_max`.
* **Everything is annualized.** All figures are whole numbers per year: hourly x2080, daily x260, weekly x52, monthly x12, yearly as-is.
* **Suspicious periods are corrected.** Imported jobs frequently arrive with every salary stamped `yearly` even when the value is an hourly wage. A period stamped `yearly` (or missing) is therefore inferred from the value's magnitude: below 500 is treated as hourly, below 10,000 as monthly, everything else as yearly. Explicit `hourly`, `daily`, `weekly`, and `monthly` stamps are trusted as-is.
* **Implausible values are dropped.** After annualizing, only figures between 10,000 and 10,000,000 count. Placeholder and corrupted values (a \$1 salary, a phone number in a salary field) are excluded and counted in `excluded_implausible`.
* **One currency.** Stats are computed in your board's dominant currency. Jobs priced in another currency are excluded and counted in `excluded_other_currency` rather than silently mixed in.
* **Percentiles use midpoints.** `p25`, `median`, and `p75` are percentiles of each job's annualized salary midpoint, `(min + max) / 2`.

## Fields

<ResponseField name="currency" type="string | null">Your board's dominant salary currency. `null` when no live job publishes salary data (then `overall` is `null` too).</ResponseField>
<ResponseField name="total_active_jobs" type="number">Live jobs on your board (active, unexpired).</ResponseField>
<ResponseField name="salaried_jobs" type="number">Live jobs that publish salary data in the dominant currency. This is the sample behind `overall`.</ResponseField>
<ResponseField name="excluded_other_currency" type="number">Live salaried jobs left out because they are priced in another currency.</ResponseField>
<ResponseField name="excluded_implausible" type="number">Live salaried jobs left out because their annualized pay fell outside the 10,000 to 10,000,000 plausibility window.</ResponseField>
<ResponseField name="periods" type="object">How the underlying jobs pay after period inference: counts keyed by effective period, e.g. `{ "yearly": 60, "hourly": 25 }`.</ResponseField>
<ResponseField name="overall" type="object | null">Distribution across every salaried job: `count`, `min`, `max`, `avg`, `p25`, `median`, `p75`.</ResponseField>
<ResponseField name="by_category" type="array">Per-category stats: `id`, `name`, and `slug` plus the same distribution fields. Up to 100 rows.</ResponseField>
<ResponseField name="by_job_type" type="array">Per-job-type stats: `value` (e.g. `full-time`) plus the distribution fields. Up to 20 rows.</ResponseField>
<ResponseField name="by_location" type="array">Per-location stats: `value` (the job's location text, e.g. `Austin, TX`) plus the distribution fields. Up to 15 rows.</ResponseField>

<Note>
  A group appears in a breakdown only when it has at least 3 salaried jobs, so thin samples never produce misleading numbers. Rows are ordered by `count` descending.
</Note>

On failure the endpoint returns a `500` with `{ "error": { "message": "...", "code": "db_error" } }`.
