# XH1B Archive API: Reference

Search H-1B labor condition applications and linked employer, wage, layoff, and public contract records. Coverage varies by source and year. Filing wage offers are not payroll observations; worker requests are not confirmed hires.

## What this is

A public API over the available XH1B disclosure records. Search H-1B labor condition applications from the Department of Labor and linked employer, attorney, worksite, wage benchmark, layoff, contract, hospital, university, corporate registration, and court records. Coverage varies by source and year. A filing is not a USCIS approval, a confirmed hire, or a current vacancy. Wage offers are not payroll observations.

Every record traces back to a source government file. Each ingest stores the file's SHA-256 hash before parsing, so any figure in this API can be verified against the original disclosure file.

## Access

- **No API key for public records.** Public endpoints are open and read-only except the receipt-submission endpoints under the **Submit** tag. The **Recon** endpoints require account authentication and are private to that account. They accept a signed-in web session or an account API key.
- **Rate limits:** reads are limited to 20 requests/minute per IP (burst 40). Anonymous writes are limited to 5/minute.
- **Caching:** responses carry `Cache-Control: s-maxage` + `stale-while-revalidate`, so a cache in front of the API (Cloudflare, your CDN) absorbs repeat traffic. Respect it: deep page-walks beyond page 10 of any list are cached-misses and will be slow.

## Conventions

- **Pagination:** `page` (1-based) + `perPage`. List endpoints cap `perPage` server-side (typically 50).
- **Sorting:** `sortBy` + `sortDir=asc|desc` where noted. Sort keys are validated allowlists; unknown keys fall back to the default sort.
- **IDs:** entity identifiers are UUIDs. Employers additionally have URL `slug` values, used on the website at `/org/<slug>`.
- **Errors:** `429` rate-limited, `400` bad parameter, `422` well-formed but no data to return, `404` unknown entity.

## Data license

Data is published under **CC BY 4.0**. Attribute "XH1B Archive" and link the entity page you cite. Citation formats (APA/MLA/Chicago/AP) are generated on every entity page. See the [newsroom](/press) for methodology and the [license terms](/terms).

## Get started

```bash
# National headline stats
curl https://www.xh1b.org/api/stats

# Search everything (employers, firms, cases, hospitals, contracts)
curl "https://www.xh1b.org/api/search?q=infosys"

# Ranked employers, employer contacts, and law firms (DOL records)
curl "https://www.xh1b.org/api/leaderboard?tab=employers&perPage=20"
```

## Machine discovery

- This document (JSON): [`/api/openapi`](/api/openapi)
- Markdown version of these docs: [`/md/api`](/md/api). Use the direct URL because the edge cache may return HTML for negotiated requests.
- Agent discovery: [`/.well-known/api-catalog`](/.well-known/api-catalog) (RFC 9727), [`/llms.txt`](/llms.txt)

Machine-readable spec (OpenAPI 3.1): `/api/openapi` · Interactive docs: `/api` · Markdown docs: `/md/api`. Use the direct URL because the edge cache may return HTML for negotiated requests.

## Contents

- [Account](#account) (4)
- [Entities](#entities) (4)
- [Employers](#employers) (21)
- [Search](#search) (6)
- [OFLC Programs](#oflc-programs) (6)
- [Leaderboard](#leaderboard) (3)
- [Homepage](#homepage) (3)
- [Persons](#persons) (2)
- [Law Firms](#law-firms) (7)
- [Geography](#geography) (25)
- [SOC Codes](#soc-codes) (5)
- [Enforcement](#enforcement) (2)
- [Hospitals](#hospitals) (3)
- [Education](#education) (2)
- [Ghost Office](#ghost-office) (3)
- [Graph](#graph) (1)
- [Medical](#medical) (3)
- [Industries](#industries) (2)
- [Submit](#submit) (2)
- [Admin](#admin) (6)
- [Pipeline](#pipeline) (1)
- [Service](#service) (3)
- [Recon](#recon) (5)
- [News](#news) (5)

## Account

### GET /api/v1/notifications

Read matching publications or regenerate their changes

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `publication` | no |  |
| `cursor` | no |  |
| `after` | no |  |
| `limit` | no |  |

### GET / POST / DELETE /api/account/keys

List the signed-in account's API keys · Create an API key · Revoke an API key

**DELETE parameters**

| Parameter | Required | Example |
|---|---|---|
| `id` | yes |  |

### GET /api/account/me

Account identity, tier, and allowances

### POST /api/account/keys/rotate

Rotate an API key

## Entities

### GET /api/graph/evidence

Supporting source records for an entity relationship, paginated

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `source` | yes | employer:00000000-0000-0000-0000-000000000001 |
| `target` | yes | person:00000000-0000-0000-0000-000000000002 |
| `type` | yes | director |
| `offset` | no | 0 |

### GET /api/metrics-catalog

Source entity names and research ranking signals, with keyset pagination

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `kind` | no | employer |
| `after` | no |  |
| `limit` | no | 500 |

### GET /api/metrics-entity-evidence

Bounded source associations for a filing person or firm

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `kind` | yes | firm |
| `slug` | yes | Fragomen, Del Rey, Bernsen & Loewy LLP |

### POST /api/entity-exposure

Read stored displacement exposure for up to 32 entity links

## Employers

### GET /api/metrics-evidence

Bounded employer research packet with explicit section populations and coverage

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `slug` | yes | example-employer |

### GET /api/employer-lcas

Employer LCA filings (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |

### GET /api/employer-attorneys

Employer's attorneys

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |

### GET /api/employer-worksites

Employer's worksite locations

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |

### GET /api/employer-exec-comp

Employer's executive compensation (SEC DEF 14A), paginated

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |

### GET /api/employer-insider-signals

Employer's insider timing signals, paginated

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |

### GET /api/employer-insider-txns

Employer's insider sale transactions, paginated

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |

### GET /api/employer-persons

Employer's key people

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |

### GET /api/employer-perm

Employer PERM labor-cert filings

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-pw

Employer prevailing-wage determinations

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-contracts

Employer federal contracts

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-state-contracts

Employer state-procurement contracts, paginated

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-displacement-events

Employer WARN↔LCA displacement-signal matches, paginated

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-officers

Employer directors / officers / beneficial owners

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-board

SEC proxy board slates and changes between stored years

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `year` | no | latest stored |
| `page` | no | 1 |
| `timelinePage` | no | 1 |
| `sort` | no | name | title |

### GET /api/employer-h2a

Employer H-2A agricultural filings

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-h2b

Employer H-2B seasonal filings

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-cw1

Employer CW-1 Northern Marianas filings

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/employer-warns

Employer WARN (mass-layoff) notices (paginated)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/export-employer

Public CSV export of an employer's source data (dataset: lcas | warns | contracts; CC-BY 4.0, capped at 10,000 rows)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `slug` | yes | infosys-limited-1be87174c7 |
| `dataset` | yes | lcas |

### GET /api/employer-court-cases

Employer federal lawsuits (CourtListener / RECAP)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

## Search

### GET /api/search-mark/v1/[kind]/[code]

Census atlas state or county outline for search results

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `kind` | yes |  |
| `code` | yes | Lowercase state abbreviation or five-digit county FIPS code |

### GET /api/search

Full-text + ILIKE search

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `q` | yes | Tata |

### GET /api/search-catalog

Public navigation search catalog packaged with the website build

### GET /api/stats

National stats

### GET /api/search-catalog/[part]

Saved search names by set: states, counties, companies, people, firms, towns

### GET /api/lcas

National H-1B filings browser, filtered by decision year (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `year` | yes | 2023 |
| `status` | no | CERTIFIED |
| `soc` | no | 15 |
| `belowPrevailing` | no | 1 |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 10 |

## OFLC Programs

### GET /api/pw-record-context

Related wage determinations and employment filings for a prevailing wage record

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `caseNumber` | yes | P-500-21025-030134 |
| `section` | yes | peers |
| `page` | no | 1 |
| `perPage` | no | 8 |
| `sortBy` | no | date |
| `sortDir` | no | desc |

### GET /api/perm

National PERM labor-certification browser, filtered by decision year (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `year` | yes | 2023 |
| `status` | no | certified |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 10 |

### GET /api/pw

National prevailing-wage determination browser, filtered by determination year (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `year` | yes | 2023 |
| `status` | no | issued |
| `sortBy` | no | determination_date |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 10 |

### GET /api/h2a

National H-2A agricultural browser, filtered by employment begin year (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `year` | yes | 2023 |
| `status` | no | certified |
| `sortBy` | no | employment_begin_date |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 10 |

### GET /api/h2b

National H-2B seasonal browser, filtered by employment begin year (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `year` | yes | 2023 |
| `status` | no | certified |
| `sortBy` | no | employment_begin_date |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 10 |

### GET /api/cw1

National CW-1 Northern Marianas browser, filtered by employment begin year (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `year` | yes | 2023 |
| `status` | no | certified |
| `sortBy` | no | employment_begin_date |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 10 |

## Leaderboard

### GET /api/leaderboard

Ranked employers, employer contacts, and law firms from DOL records

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `tab` | yes | employers |
| `page` | no | 1 |
| `perPage` | no | 8 |
| `families` | no | 1 |
| `sort` | no | theft |

### GET /api/comp-execs

All ranked executive compensation (SEC DEF 14A) at H-1B employers, paginated + sortable

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `sortBy` | no | comp_rank |
| `sortDir` | no | asc |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/enforcement/leaderboard

Sortable employer leaderboard (caught/missed modes)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `mode` | no | missed |
| `sortBy` | no | wageTheft |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 25 |

## Homepage

### GET /api/evidence

WARN notices with nearby H-1B requests, position counts, and job titles

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `page` | no | 1 |
| `perPage` | no | 8 |
| `sortBy` | no | date |
| `sortDir` | no | desc |

### GET /api/chart.svg

Standalone chart export as native SVG (kind: wage-trend | denial-trend | trend)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `kind` | no | wage-trend |
| `slug` | no | infosys-limited-1be87174c7 |
| `data` | no | {"title":"Example","unit":"filings","points":[{"x":2023,"y":4},{"x":2024,"y":6}]} |

### GET /api/chart.png

Standalone chart export as PNG (kind: wage-trend | denial-trend | trend; rate-limited)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `kind` | no | wage-trend |
| `slug` | no | infosys-limited-1be87174c7 |
| `data` | no | {"title":"Example","unit":"filings","points":[{"x":2023,"y":4},{"x":2024,"y":6}]} |

## Persons

### GET /api/person-lcas

Person's LCA filings (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `personId` | yes | uuid |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |

### GET /api/person-employers

Employers a person (attorney/POC) has filed LCAs for

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `personId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |

## Law Firms

### GET /api/firm-lcas

Firm LCA records; select full history for filters

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `name` | yes | Fragomen |
| `history` | no | full |
| `employer` | no | google-llc |
| `year` | no | 2025 |
| `soc` | no | 15-1252 |
| `naics2` | no | 54 |
| `state` | no | CA |
| `status` | no | Certified |
| `wage` | no | below |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/firm-cases

Court cases and shared clients for a matched law firm. kind selects direct, client, or shared evidence.

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `name` | yes | Fragomen |
| `kind` | yes | shared |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/firm-clients

Firm clients or paired client wage comparisons

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `name` | yes | Fragomen |
| `variant` | no | wages |
| `q` | no | Google |
| `sortBy` | no | below_bls |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/firm-options

Search occupations in a firm's filing history

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `name` | yes | Fragomen |
| `q` | no | software |

### GET /api/firm-peers

Compare paired wages within one occupation and decision year

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `name` | yes | Fragomen |
| `soc` | yes | 15-1252 |
| `year` | yes | 2025 |
| `minimum` | no | 30 |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/firm-activity

Firm occupations, annual outcomes, or worksite states

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `name` | yes | Fragomen |
| `dimension` | yes | year |
| `employer` | no | google-llc |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/firm-attorneys

Law firm's attorneys (paginated)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `firm` | yes | Fragomen |
| `page` | no | 1 |
| `perPage` | no | 8 |

## Geography

### GET /api/county-lcas

County LCA filings (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `fips` | yes | 06085 |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |

### GET /api/county-employers

County employers with BLS gap

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `fips` | yes | 06085 |

### GET /api/county-soc

County SOC wage gaps (sorted by theft)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `fips` | yes | 06085 |

### GET /api/zip-lcas

ZIP LCA filings (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `zip` | yes | 94043 |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |

### GET /api/zip-employers

ZIP employers

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `zip` | yes | 94043 |

### GET /api/zip-soc

ZIP SOC breakdown

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `zip` | yes | 94043 |

### GET /api/state-lcas

State LCA filings (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |

### GET /api/vertical-state-lcas

Vertical (medical/education/tech/finance) state LCA filings from a precomputed window (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `kind` | yes | medical |
| `state` | yes | CA |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |

### GET /api/state-warns

State WARN notices (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |
| `sortBy` | no | effective_date |
| `sortDir` | no | desc |

### GET /api/state-soc

State SOC wage gaps (sorted by theft)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |

### GET /api/state-lawfirms

State law firms with BLS gap

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |

### GET /api/state-procurement

Largest 25 state source records, paginated. CT records expose payments, including grants, separately from contract awards.

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CT |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/state-contracts

State federal contracts

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |

### GET /api/county-warns

County WARN notices

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `fips` | yes | 06085 |

### GET /api/scoped-institutions

IPEDS institutions scoped to state/county (sortable: suppression|volume, or sortBy=institution_name|h1b_count|h1b_median_wage|pct_of_bls|pct_of_ipeds_all + sortDir)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `scope` | no | state |
| `id` | yes | TX |
| `sort` | no | volume |
| `sortBy` | no | pct_of_ipeds_all |
| `sortDir` | no | asc |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/scoped-hospitals

Hospital wage-gap breakdown scoped to state/county

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `scope` | no | state |
| `id` | yes | TX |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/scoped-counties

County-level H-1B activity scoped to a state (medical or education vertical)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | TX |
| `vertical` | no | medical |
| `minLcas` | no | 5 |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/hospital-wage-gap

Hospital wage-suppression leaderboard (attending or residency mode)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `mode` | no | attending |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/education-wage-gap

Education faculty wage-suppression leaderboard (suppression or volume sort)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `sort` | no | suppression |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/state-top-employers

State top employers by H-1B volume

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/zip-warns

ZIP WARN notices

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `zip` | yes | 94043 |

### GET /api/county-contracts

County federal contracts

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `fips` | yes | 06085 |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/county-lawfirms

County immigration law firms

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `fips` | yes | 06085 |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/state-counties

State county H-1B rankings

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/state-zips

State top ZIPs by H-1B volume

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |
| `page` | no | 1 |
| `perPage` | no | 8 |

## SOC Codes

### GET /api/soc-employers

Employers for SOC code

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `code` | yes | 15-1252 |

### GET /api/soc-filings

SOC code filings, certified H-1B (sortable, below-prevailing facet)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `code` | yes | 15-1252 |
| `sortBy` | no | decision_date |
| `sortDir` | no | desc |
| `belowPrevailing` | no | 1 |

### GET /api/soc-wage-trend

SOC yearly median offered wage vs BLS median (complete series)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `code` | yes | 15-1252 |

### GET /api/scoped-specialties

SOC/specialty breakdown scoped to state/county/employer (sortable: volume|wage|suppression)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `scope` | no | state |
| `id` | yes | TX |
| `socPrefixes` | no | 29-%,31-2% |
| `sort` | no | suppression |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/soc-scoped-employers

Employers in a geo scope filtered by SOC prefix (live GROUP BY, medical/education verticals)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `scope` | no | county |
| `code` | yes | 06085 |
| `socPrefixes` | no | 29-%,31-2% |
| `minFilings` | no | 3 |
| `sortBy` | no | count |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 8 |

## Enforcement

### GET /api/record-revisions

Agency revision history for one tracked record (table + recordKey, paginated; page size fixed at the shared table default)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `table` | yes | lcas |
| `recordKey` | yes | I-200-26001-001 |
| `page` | no | 1 |

### GET /api/court-cases

Federal lawsuits naming matched employers, newest first (paginated; backs the /whd court ledger)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `page` | no | 1 |
| `perPage` | no | 8 |

## Hospitals

### GET /api/hospital-specialties

Hospital H-1B filings by clinical SOC (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |
| `sortBy` | no | count |
| `sortDir` | no | desc |

### GET /api/hospital-intermediaries

Staffing agencies / sister facilities placing H-1B workers at a hospital (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `ccn` | yes | 330059 |
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |
| `sortBy` | no | lca_count |
| `sortDir` | no | desc |

### GET /api/hpsa-hospitals

Hospitals in an HPSA-designated county with H-1B wage signal

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `hpsaId` | yes | HPSA-uuid |
| `state` | yes | CA |
| `page` | no | 1 |
| `perPage` | no | 8 |

## Education

### GET /api/university-specialties

University H-1B filings by SOC (sortable)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `employerId` | yes | uuid |
| `page` | no | 1 |
| `perPage` | no | 8 |
| `sortBy` | no | count |
| `sortDir` | no | desc |

### GET /api/education-intl-concentration

Institutions by international-student concentration (IPEDS nonresident share)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `sortBy` | no | pct |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 8 |

## Ghost Office

### GET /api/agent-employers

Employers represented by a registered agent (sortable, paginated)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `nameKey` | yes | CT CORPORATION SYSTEM |
| `sortBy` | no | total_h1b_count |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/ghost-office

Ghost-office (shell-address) employer signals (sortable, paginated)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `minScore` | no | 3 |
| `individualRa` | no | true |
| `page` | no | 1 |
| `perPage` | no | 25 |

### GET /api/ghost-office/networks

Ghost-office networks (clusters of employers at one shell address)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `top` | no | 20 |

## Graph

### GET /api/graph/expand

Expand graph neighbors for a node (employer/person/firm/agent/agency)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `nodeId` | yes | employer:uuid |

## Medical

### GET /api/medical-shortage

Counties importing H-1B physicians despite adequate MD supply (the 'doctor shortage' counter-evidence)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `sortBy` | no | h1b_md_lcas |
| `sortDir` | no | desc |
| `minLcas` | no | 80 |
| `minPop` | no | 200000 |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/state-hpsa-counties

State counties ranked by primary-care HPSA designations

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `state` | yes | CA |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/county-hpsas

Health Professional Shortage Areas in a county

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `fips` | yes | 06085 |
| `page` | no | 1 |
| `perPage` | no | 8 |

## Industries

### GET /api/vertical-employers

Employer list for an industry vertical (tech/finance), geo-scoped, from the employer_vertical_stats MV

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `vertical` | yes | tech |
| `scope` | no | state |
| `code` | no | CA |
| `minFilings` | no | 3 |
| `sortBy` | no | filings |
| `sortDir` | no | desc |
| `page` | no | 1 |
| `perPage` | no | 8 |

### GET /api/worksite-dots

Worksite dot-density points for the /map overlay (worksite_dot_grid MV, top cells by workers)

## Submit

### POST /api/whistleblower

Submit an anonymous whistleblower drop (message + optional PGP public key + files already uploaded to /api/whistleblower/upload)

### POST /api/receipts

Submit a rejection receipt

## Admin

### POST /api/admin/receipts

Verify or reject a receipt

### POST /api/admin/events

Verify or reject a displacement event

### POST /api/admin/employers/merge

Merge an employer alias into a corporate family (entity identity)

### GET /api/admin/system

Live system monitor snapshot (host CPU/RAM, PostgreSQL activity, Docker stats)

### POST /api/web-vitals

Core Web Vitals beacon (LCP/INP/CLS/TTFB/FCP), recorded into perf_web_vitals + perf_spans for slow TTFB

### POST /api/web-request

Per-request proxy-timing beacon fired by edge middleware (sampled). Signed with the x-beacon-sig HMAC header; unsigned posts are rejected. Records pre-handler proxy time into perf_spans kind='proxy_time' — never the route handler's latency or final status (audit T04).

## Pipeline

### GET /api/pipeline/runs

Ingest pipeline run history (admin-only; filter failed runs; fixed 20 per page)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `filter` | no | failed |
| `page` | no | 1 |

## Service

### GET /api/health

Consolidated health probe (db, derived_data, ingest_pipeline, frank, ocr, disk, scheduler); 503 with body when degraded

### GET /api/indexnow/key

IndexNow key verification file (404 when INDEXNOW_KEY unset)

### GET /api/status

Public uptime/inventory status (data freshness snapshot)

## Recon

### GET / POST /api/recon

Load the signed-in user's saved identity research searches · Run an identity research search

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `page` | no | Zero-based history page. Each page has 20 saved searches. |

### GET / POST /api/recon/matters

List the account's matters · Create a matter

### GET / DELETE /api/recon/matters/[id]

One matter with its attached runs · Delete a matter

### GET /api/recon/matters/[id]/export

Download a matter's evidence packet

### GET /api/recon/records

Inspect a run's retained claims

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `search_id` | yes |  |
| `matter_id` | no |  |
| `claim` | no |  |
| `group` | no |  |
| `page` | no |  |
| `perPage` | no |  |

## News

### GET /api/news

News wire pages: ?from/?to (YYYY-MM-DD) + ?page (1-based, ≤10000), optional ?sources (comma-separated source list)

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `from` | yes | 2026-09-04 |
| `to` | yes | 2026-09-05 |
| `page` | yes | 1 |

### GET /api/news/poll

Wire liveness probe: newest story id + newest day + optional new-story count since ?since

**GET parameters**

| Parameter | Required | Example |
|---|---|---|
| `since` | no | 2026-09-04T10:00:00Z |

### POST /api/news/vote

Anonymous up/down vote on a wire story (storage-only; a visitor UUID cookie is issued on the first vote)

### POST /api/push/subscribe

Store a web-push subscription for the news digests (PushSubscription JSON from the browser)

### POST /api/push/unsubscribe

Remove a web-push subscription by endpoint (idempotent)

## API discovery

- API catalog (RFC 9727 linkset): `/.well-known/api-catalog`
- Health probe: `/api/health`
- Site: XH1B
