Getting started
- Create a free account — 50 lookups/month, no credit card required.
- Verify your email — your first API key is generated automatically.
- Create or rotate additional keys any time from your account page.
- Make your first API call:
curl -H "X-Api-Key: YOUR_API_KEY" \
"https://api.fastdol.com/v1/employers?name=walmart&state=CA"Data sources
Every employer profile is an aggregate over the data sources listed below. Source-specific fields use a consistent prefix — osha_*, whd_*, cms_* — so you can identify provenance from the field name alone.
| Source | Agency | What's in the data | Scale |
|---|---|---|---|
| OSHA | Occupational Safety and Health Administration | Inspections, violations, penalties, and fatality investigations — with inspection-type and severity breakdowns. | 2.7M+ inspections |
| WHD | Wage and Hour Division | Department of Labor wage-theft investigations with back wages owed and affected employee counts. | $4.6B in back wages |
| MSHA | Mine Safety and Health Administration | Mine safety violations, inspections, and assessed penalties across all U.S. mining operations. | 2.5M+ violations |
| EPA | Environmental Protection Agency | Clean Air, Clean Water, RCRA, and SDWA compliance via EPA ECHO — inspections, formal actions, and penalties. | $1.2B in EPA penalties |
| NLRB | National Labor Relations Board | Unfair labor practice charges and union-representation case history. | 1.7M+ cases |
| FMCSA | Federal Motor Carrier Safety Administration | DOT-regulated motor carrier registration, operation type, and safety-basic scores. | 107K+ DOT-registered carriers |
| OFLC | Office of Foreign Labor Certification | H-1B, H-2A, and H-2B labor condition applications with prevailing-wage ratios. | 37K+ LCAs |
| ITA | OSHA Injury Tracking Application | OSHA Form 300A self-reported DART and TRIR rates by establishment — employer-submitted, refreshed annually when OSHA publishes the next year's release. | 162K self-reported establishments |
| BLS | Bureau of Labor Statistics (SOII) | BLS Survey of Occupational Injuries and Illnesses industry-wide TRIR/DART averages for peer-percentile ranking — refreshed annually with each BLS Table 1 release. | 1,045 NAICS covered |
| SAM | System for Award Management | Federal debarment, suspension, and ineligibility exclusions — governs who can win federal contracts. | 572 excluded employers |
| CMS | Centers for Medicare & Medicaid Services | Five-star ratings, deficiencies, civil money penalties, and staffing hours per resident per day. | 14.7K nursing facilities |
| CPSC | Consumer Product Safety Commission | Consumer product recalls tied to the responsible manufacturer or distributor. | 22K+ employers w/ recalls |
| NHTSA | National Highway Traffic Safety Administration | Vehicle recalls and defect complaints tied to OEMs and upfitters. | 6.6K manufacturers w/ recalls |
| USAspending | USAspending.gov | Federal contracts and assistance (grants, loans) awarded to private and non-profit entities. Refreshed monthly from the Award Data Archive. Attributed at parent-company level via name-pattern matching against our curated parent registry, so a Walmart store profile surfaces Walmart Inc.'s federal totals rather than the (usually zero) per-store number. | 166M+ federal award records |
| SEC | Securities and Exchange Commission (XBRL companyfacts) | Per-public-reporter financial scale — revenue, net income, employee count, total assets — from XBRL-tagged 10-K filings. | 9K+ public-company filers |
| SEC | Securities and Exchange Commission (Litigation Releases) | Formal civil enforcement actions filed in federal court — defendant, date, summary, and penalty amount over a 5-year window. | 2.5K+ enforcement actions |
| UVA | UVA Corporate Prosecution Registry | Federal corporate prosecutions, plea agreements, DPAs and NPAs — compiled by UVA Law School. | 33K+ employers w/ prosecutions |
Authentication
Include your API key in the X-Api-Key header with every request. View existing keys (masked) and create new ones on the account page. Each account supports up to 5 active keys; rotating a key gives the old value a 48-hour grace period.
Endpoints
Search employers
| Param | Type | Description |
|---|---|---|
| name | string | Employer name (fuzzy match) |
| ein | string | Exact EIN match |
| state | string | 2-letter state code |
| zip | string | 5-digit ZIP code |
| naics | string | 4-digit NAICS prefix |
| parent_only | bool | Returns one result per parent company with aggregate stats. Default false. |
| limit | int | Results per page (1-100, default 20) |
| offset | int | Pagination offset |
Get employer detail
Lookup by EIN
Exact EIN lookup. Dashes are optional (94-3067788 or 943067788). When multiple locations share an EIN, add state to narrow. Returns 404 if no employer is found with that EIN.
Inspection history
Returns inspection records for an employer, ordered by date (newest first). Counts as 1 lookup against your quota.
Violation detail for an inspection
All citations issued on a single OSHA inspection. activity_nr is the numeric OSHA activity number returned by the inspection history endpoint.
Risk history
Per-employer detail records
Each profile links to its underlying per-record detail — paginated, newest-first. All take the employer_id from a search or detail response, accept limit and offset, and count as 1 lookup.
In order: OSHA Severe Injury Reports; per-case WHD wage enforcement; OSHA accident & fatality investigations; SEC litigation releases for the parent company; USAspending federal contract & assistance awards; and same-NAICS, same-state peer establishments for benchmarking.
Parent company rollup
Aggregate risk across all locations of a parent company. name is required; add state to disambiguate common names.
Cluster lookups (resolved entities)
Two cluster-grain endpoints surface FastDOL's entity-resolution output directly. Each returns the cluster's confidence_band (high / med / low), the weakest-link match weight, cohesion + fragility flags, and the members of the cluster. Band cutoffs are tied to measured held-out precision (≥97.5% Wilson 95% lower bound at high, ≥98.7% at med); the full methodology document is available under NDA.
A physical-site cluster: all records that share an establishment_id (one address, possibly aggregated across federal sources). Use this to drill from a parent (a multi-site business) to one of its locations and see the underlying records. Singletons return a single member with confidence: null — the record is the establishment by definition; no merge happened.
A rolled-up-business cluster: every establishment (site) under one company_id. The response lists one row per establishment sorted by total OSHA penalty (worst first), each carrying its own establishment-level confidence and aggregated enforcement stats. Drill into a specific site via /v1/establishments/{id} or to a specific record via /v1/employers/{employer_id}.
confidence: null. The cluster id is the record's own employer_id, so calling /v1/establishments/{employer_id}for a singleton returns a one-member response — useful for uniform client code that doesn't need to special-case singletons.Batch lookup
# Up to 100 items per synchronous request
{
"lookups": [
{"name": "Walmart", "state": "ID", "zip": "83669"},
{"name": "Amazon", "state": "CA"},
{"name": "Target", "zip": "55403"}
]
}Each item can include name, ein, employer_id, state, zip, and city. The response wraps each input in an object with query, match (the employer profile or null), and confidence, plus top-level matched / unmatched counts. For batches over 100 items, use CSV upload (below), which supports up to 500 rows.
CSV upload
Upload a CSV with employer names. Returns a CSV with risk profiles appended. Max 500 rows, 5MB. Content-Type: multipart/form-data, field name file.
Industry benchmarks
BLS SOII industry TRIR/DART benchmarks by NAICS. The code must be exactly 4 digits (e.g. 2361); call /v1/industries/naics-codes for the list of covered codes.
Bulk export Enterprise
Pull up to 100,000 employer records matching a structured query — filter, threshold, and sort in a single request. Runs async: submit a job, poll for status, download the file. Requires the export:bulk scope. Contact sales to enable.
Want the entire dataset rather than a filtered slice? Bulk export is capped at 100,000 rows — for a full local copy use Full dataset (snapshots) below.
Request
{
"format": "csv", // "csv" or "json" (NDJSON)
"max_rows": 50000, // 1 - 100,000
"sort_by": "fatalities",
"sort_dir": "desc", // "asc" or "desc" (default desc)
"filters": {
"states": ["CA", "TX", "FL"],
"naics_codes": ["2361", "2362"],
"min_penalties": 100000,
"has_fatalities": true
}
}
→ 202 { "job_id": "...", "status": "queued", "poll_url": "..." }At least one filter is required. An unfiltered export would scan 2M+ rows and is refused.
Polling
GET /v1/export/{job_id}
→ {
"job_id": "...",
"status": "queued" | "running" | "finished" | "failed",
"row_count": 42187,
"file_size_bytes": 52428800,
"download_url": "...", // present only when status=finished
"expires_at": "2026-04-23T11:00:00Z"
}
GET /v1/export/{job_id}/download
→ streams the CSV or NDJSON file (24h retention)Full dataset — weekly snapshots Enterprise
The complete dataset as point-in-time Parquet — one file per table, republished every week. This is the path for a full local copy (the bulk export above is for filtered slices up to 100,000 rows). Two calls get you everything: fetch the manifest, then download each file from its presigned URL. Requires the snapshot:read scope.
1. Fetch the manifest
curl -s -H "X-Api-Key: $KEY" \
https://api.fastdol.com/v1/snapshots/latest
→ {
"snapshot_id": "2026-W22",
"asof_date": "2026-05-29",
"total_rows": 180000000,
"total_size_bytes": 1500000000,
"files": [
{
"table": "employer_profile",
"format": "parquet",
"rows": 2250197,
"size_bytes": 344789695,
"sha256": "4855575e0c07...",
"download_url": "https://<r2-host>/...employer_profile.parquet?X-Amz-...",
"download_url_expires_in_seconds": 21600,
"status": "ready"
}
// ...one entry per table (13 in total)
]
}Omit the path for the latest snapshot, or pass an id — GET /v1/snapshots/2026-W22 — to pin a specific week. Every call mints fresh presigned URLs.
2. Download every table
Each file carries a presigned download_url (no auth header on the download itself). Loop the manifest with jq:
KEY="your_api_key"
# Pull the manifest, then download each table's Parquet to <table>.parquet
curl -s -H "X-Api-Key: $KEY" \
https://api.fastdol.com/v1/snapshots/latest > manifest.json
jq -r '.files[] | select(.status == "ready")
| [.table, .download_url] | @tsv' manifest.json \
| while IFS=$'\t' read -r table url; do
echo "downloading $table"
curl -fSL -o "$table.parquet" "$url"
done3. Verify integrity (optional)
jq -r '.files[] | "\(.sha256) \(.table).parquet"' manifest.json | sha256sum -c -
# employer_profile.parquet: OK
# inspection_detail.parquet: OK
# ...snapshot.ready to be notified the moment each weekly snapshot publishes, instead of polling for a new snapshot_id.Response format
Each employer result includes flat fields plus nested objects for benchmarks, self-reported data, accident details, and analytics. The full response shape includes ~80 fields; the OpenAPI spec linked above has the complete schema.
{
"results": [
{
"employer_id": "uuid",
"employer_name": "WALMART",
"city": "STAR",
"state": "ID",
"naics_code": "452112",
"naics_description": "Discount Department Stores",
"svep_flag": false,
"parent_name": "Walmart Inc.",
"location_count": 140,
"osha_inspections": 3,
"osha_violations": 7,
"osha_total_penalties": 15000.00,
"whd_cases": 1,
"whd_backwages_total": 5000.00,
"nlrb_cases": 2,
"epa_compliance_status": "Significant Violation",
"is_sam_excluded": false,
"agency_violation_count": 3,
"peer_violation_percentile": 87,
"peer_group_size": 342,
"industry_benchmark": { "avg_trir": 3.2, "avg_dart": 1.8, "source": "BLS SOII 2024" },
"self_reported": { "trir": 3.5, "dart_rate": 2.1, "source": "OSHA ITA Form 300A" },
"accident_summary": { "fatalities": 0, "hospitalizations": 1 },
"analytics": {
"agencies_with_activity": ["OSHA", "WHD", "EPA"],
"total_penalties_all_agencies": 22000,
"peer_penalty_percentile": 72
}
}
],
"total_count": 1,
"limit": 20,
"offset": 0
}Analytics object
The analytics object contains computed insights derived from raw enforcement data. All fields are optional — they appear only when the underlying data exists.
| Field | Type | Description |
|---|---|---|
| years_of_history | number | Years between first and most recent enforcement activity |
| days_since_last_activity | number | Days since the most recent inspection or enforcement case |
| inspection_velocity | number | Average OSHA inspections per year over history span |
| violation_velocity | number | Average violations per year over history span |
| osha_willful_pct | number | Percentage of violations classified as willful |
| osha_serious_pct | number | Percentage of violations classified as serious |
| osha_complaint_pct | number | Percentage of inspections triggered by complaints |
| osha_penalty_per_violation | number | Average OSHA penalty dollars per violation |
| whd_backwages_per_employee | number | Average WHD back wages per affected employee |
| agencies_with_activity | string[] | List of agencies with enforcement records |
| total_penalties_all_agencies | number | Sum across OSHA + WHD + MSHA + EPA |
| trir_vs_industry | number | Self-reported TRIR minus industry average (positive = worse) |
| peer_penalty_percentile | number | Penalty rank vs same NAICS + state peers (0-100) |
| peer_inspection_percentile | number | Inspection frequency rank vs same NAICS + state peers (0-100) |
Risk scoring
Risk scores range from 0–100 and combine:
- OSHA violations — willful (30 pts), repeat (15 pts), serious (3 pts)
- OSHA penalties — up to 15 pts based on dollar amount
- WHD enforcement — back wages (up to 8 pts), cases (up to 4 pts), employees violated (up to 3 pts)
Scores decay over time: full weight for last 3 years, 80% at 4 years, 60% at 5 years, 40% for older activity.
Risk tiers are derived from the score plus a few hard override conditions:
- HIGH: score ≥ 50, or any willful violation within 5 years, or 3+ repeat violations within 5 years.
- ELEVATED: score 20–49, or any workplace fatality investigation on record.
- MEDIUM: score 5–19, or any OSHA violations in the last 3 years, or enforcement actions across 2+ agencies.
- LOW: score 0–4 with no recent enforcement activity.
See methodology for the full per-component weighting and the time-decay table.
Data enrichment
Each employer profile aggregates data from every major US federal compliance source plus the UVA Corporate Prosecution Registry. Refresh cadence by source:
| Agency | Data | Refresh |
|---|---|---|
| OSHA | Inspections, violations, penalties, fatalities, inspection-type breakdown | Weekly |
| WHD | Wage enforcement cases, back wages, employees affected | Weekly |
| MSHA | Mine safety violations and assessed penalties | Weekly |
| EPA ECHO | Environmental compliance, quarters noncompliant, formal actions | Daily |
| FMCSA | DOT number, carrier registration, operation type | Daily |
| NLRB | Unfair labor practice charges, union representation cases | Daily |
| SAM.gov | Federal exclusion / debarment list | Daily |
| OFLC | H-1B / H-2 visa applications, approval rates, wage ratios | Monthly |
| ITA | OSHA Form 300A self-reported DART / TRIR rates | Annual (OSHA release) |
| BLS | SOII industry benchmark TRIR / DART by NAICS | Annual (BLS release) |
| CMS | Nursing-home five-star ratings, deficiencies, civil money penalties | Monthly |
| SEC | Enforcement actions + XBRL financial disclosures (revenue, employees, assets) | Monthly |
| CPSC | Consumer product recalls | Weekly |
| NHTSA | Vehicle and equipment recalls | Weekly |
| USAspending | Federal contracts and assistance awards, parent-rollup attribution | Monthly |
| UVA | Federal corporate prosecutions, plea agreements, DPAs / NPAs | Monthly |
Rate limits & quotas
Two limits apply on top of each other:
- Monthly quota. Your per-key allowance. Free keys get 50 lookups/month; higher tiers are per-contract. Every authenticated request that reaches a query handler counts as 1 lookup against the quota — including empty-result searches. Batch lookups count as 1 per item submitted. Current usage is visible on your account page and on every response via the
X-RateLimit-*headers. - IP-based request rate. 60 requests/minute per IP on the main search endpoints (
/v1/employers,/v1/employers/parent); 30/minute on inspection detail and per-state / per-NAICS aggregates; 10/minute on the industry metadata endpoints. Protects against scraping; applies before the monthly quota is checked.
When you exceed the rate limit you receive a 429 with {"error": "rate_limited"}. When you exceed the monthly quota you receive a 429 with {"error": "monthly_quota_exceeded"}. Both responses include a Retry-After header.
Errors
{
"detail": {
"error": "error_code",
"message": "Human-readable description"
}
}| Status | Meaning |
|---|---|
| 400 | Bad request — missing required parameter or invalid value (malformed UUID, invalid NAICS) |
| 401 | Missing or invalid API key |
| 403 | API key lacks the required scope for this endpoint |
| 404 | Direct lookup by ID/EIN not found (search returns 200 with empty list) |
| 422 | Parameter out of range (limit > 100, offset < 0) |
| 429 | Rate limit or monthly quota exceeded |
| 503 | Service degraded — pipeline freshness check or database unavailable |
200 with results: [] and a suggestions array — they are a normal response, not an error.Code examples
Python
import requests
API_KEY = "your_api_key"
BASE = "https://api.fastdol.com/v1"
# Search
r = requests.get(f"{BASE}/employers",
headers={"X-Api-Key": API_KEY},
params={"name": "Walmart", "state": "ID"})
print(r.json()["results"][0]["osha_total_penalties"])
# Batch
r = requests.post(f"{BASE}/employers/batch",
headers={"X-Api-Key": API_KEY},
json={"lookups": [
{"name": "Walmart", "zip": "83669"},
{"name": "Amazon", "state": "CA"},
]})
for item in r.json()["results"]:
print(item["query"]["name"], "->",
item["match"]["employer_id"] if item["match"] else "no match")JavaScript
const API_KEY = "your_api_key";
const BASE = "https://api.fastdol.com/v1";
const res = await fetch(
`${BASE}/employers?name=walmart&zip=83669`,
{ headers: { "X-Api-Key": API_KEY } }
);
const data = await res.json();
console.log(data.results[0].osha_total_penalties);curl
# Search
curl -H "X-Api-Key: YOUR_KEY" \
"https://api.fastdol.com/v1/employers?name=walmart&zip=83669"
# CSV upload
curl -H "X-Api-Key: YOUR_KEY" \
-F "file=@employers.csv" \
"https://api.fastdol.com/v1/employers/upload-csv" \
-o results.csv