AI Resilience API & MCP

API v2.1

Free, public API for AI career resilience data. No API key required. Rate limited to 100 requests per minute per IP.

Attribution Required

This data is free to use, share, and adapt, including commercially, under CC BY 4.0. The license requires that you credit the source with a visible link back to airesilience.org. Paste one of these wherever you display the data:

HTML
<a href="https://www.airesilience.org">AI Resilience Report</a> by <a href="https://www.careervillage.org">CareerVillage.org</a>, licensed under <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.
Plain text
AI Resilience Report by CareerVillage.org, licensed under CC BY 4.0. https://www.airesilience.org

Every API response also carries an attribution object with these values, so you can render the credit straight from the payload. Linking to the specific career page you are quoting is welcome and works as attribution too.

Full Dataset Download

Bulk CSV export of the latest quarterly snapshot — all scored occupations, sub-scores, and per-source values. Licensed under CC BY 4.0.

1,571 careers · Snapshot: 2026-10-07

Geo Dataset Download

Bulk CSV of the local layer — one row per occupation per metro/nonmetro area (~450k rows) with workers, median wage, location quotient, and the national comparison figures. May 2025 OEWS. Kept separate from the main dataset so that file stays small. Licensed under CC BY 4.0.

API Playground

/ext/api/career/

This API uses 2019 SOC codes. You can look up codes at bls.gov/soc.

Resilience scores are generated by the AI Resilience Model v1.5 (returned as data.airm_cv.version). See the Changelog for version history.

Single-Career Endpoint

GET https://www.airesilience.org/ext/api/career/{code}

Path Parameter

ParameterTypeDescription
codestringSOC code in format XX-XXXX or XX-XXXX.XX

Query Parameters

All parameters are optional. area and county are mutually exclusive.

ParameterTypeDescription
areastringOEWS area ID (5-digit CBSA for metros, 6-7 digit code for nonmetro regions). Adds a local block with that area's workers, median wage, and location quotient. Find IDs via the Area Search Endpoint.
countystring5-digit county GEOID (2-digit state FIPS + 3-digit county FIPS, e.g. 25025 for Suffolk County, MA). Resolves to the county's OEWS area, then behaves exactly like area. Handy when you already have a location from a geocoder.
bandstringRestrict expertise.bands to one experience band: entry, mid, or senior. Omitted, all three are returned.

Response Format

Success (200)

Fields are grouped by concern. All numeric scores are on a 0-1 scale unless otherwise noted. Any field can be null when the underlying data is unavailable for that occupation.

Every successful response also carries a top-level attribution object (required, text, url, license, sources) so you can render the required credit directly from the payload. See Attribution.

Core

FieldTypeDescription
data.codestringSOC code
data.namestringCareer name
data.nameShortstringShort display name
data.slugstringURL slug used on airesilience.org
data.levelstringSOC hierarchy level: "major", "minor", "broad", or "detailed"
data.descriptionstringPlain-text occupation description
data.urlstringLink to the full career report page
data.lastUpdatedstringDate (YYYY-MM-DD) of the latest data snapshot

aiResilience

FieldTypeDescription
data.aiResilience.scorenumberCombined AI resilience score (0-1, higher = more resilient)
data.aiResilience.labelstringOne of: "Highly Resilient" (80.1-100%), "Resilient" (65.1-80%), "Mostly Resilient" (50.1-65%), "Somewhat Resilient" (35.1-50%), "Not Very Resilient" (22.1-35%), or "Vulnerable" (0-22%)
data.aiResilience.confidencestringConfidence level (High, Medium-high, Medium, Low-medium, Low)
data.aiResilience.confidenceScorenumber | nullNumeric confidence (0-100) behind the confidence level: points for the number of sources covering the career plus points for how tightly those sources agree
data.aiResilience.explanationstringHuman-readable explanation of the resilience label

airm_cv (AI Resilience Model, CareerVillage)

FieldTypeDescription
data.airm_cv.versionstringAI Resilience Model version (e.g., "v1.5"). See the Changelog for version history.
data.airm_cv.percentilenumberCareerVillage internal model percentile (0-1)
data.airm_cv.labelstring"High", "Medium", or "Low"
data.airm_cv.rawScorenumberRaw weighted percentile from the CV model

sources

Per-source signals that feed the combined resilience score. Percentiles are 0-1 within their respective populations.

FieldTypeDescription
data.sources.anthropicobjectAnthropic Economic Index: percentile, rawScore
data.sources.microsoftobjectMicrosoft AI Applicability: percentile, rawScore
data.sources.wrtmjobjectWill Robots Take My Job: percentile, label, rawRiskPercent, growth, volume
data.sources.openaiobjectOpenAI Signals usage-based exposure: percentile, rawScore (null where uncovered)
data.sources.althoffobjectAlthoff wage-bill exposure: wageBillPercentile, rawScore (null where uncovered)
data.sources.manningobjectManning adaptive capacity: adaptiveCapacityPercentile, adaptiveCapacityRawScore (null where uncovered)
data.sources.lted_blsOpportunityobjectBLS opportunity (the LTED subscore): score, label

subscores

FieldTypeDescription
data.subscores.meaningfulHumanContributionobjectscore (0-1), label (High/Medium/Low)
data.subscores.sustainedEconomicOpportunityobjectscore (0-1), label (High/Medium/Low)

stepsToTake

FieldTypeDescription
data.stepsToTakestring[]AI-generated suggested actions for students. Empty array when not available.

tasks

Populated for detailed occupations only. Sorted by automationLikelihood ascending (most resilient first).

FieldTypeDescription
data.tasks[].idstringO*NET task ID
data.tasks[].taskstringTask description
data.tasks[].taskTypestring"Core" or "Supplemental"
data.tasks[].automationLikelihoodnumber0-1; lower = more resilient
data.tasks[].resilienceScorenumberConvenience: 1 − automationLikelihood
data.tasks[].expertiseLevelnumber0-1 expertise the task requires (Autor & Thompson anchors; relative to the occupation). The raw input to data.expertise, so you can rebuild the career-level numbers yourself.
data.tasks[].analysisDatestringDate the automation estimate was generated (ISO 8601)

expertise (Experience Outlook — added in v1.1)

Career-level expertise shift derived from the per-task tasks[].expertiseLevel and tasks[].automationLikelihood scores — the same math behind the site's Experience Outlook panel.

FieldTypeDescription
data.expertiseobjectnull when no tasks carry both automation and expertise scores (the career page hides its Experience Outlook panel in the same case)
data.expertise.deltaExpertisenumberCareer-level ΔExpertise: average expertise of tasks surviving automation minus average expertise of all tasks. Positive = AI removes low-expertise tasks (the barrier to entry rises); negative = AI reaches the expert tasks. null when no tasks survive the automation threshold
data.expertise.deltaExpertisePercentilenumberPercentile rank (0-100) of the ΔExpertise value across all scored detailed careers
data.expertise.routineobjectFor the career's routine tasks (lowest-expertise slice): resilience (weighted avg, 0-1) and erosion (weighted share at/past the automation threshold, 0-1)
data.expertise.expertobjectSame two metrics for the career's expert tasks (highest-expertise slice)
data.expertise.forecastobjectTen-year outlook vs the average occupation. wage and employment each carry center / low / high (±1 s.e.); unit spells out the scale; capped is true when the exposure exceeded ±2 SD and was clamped. null when ΔExpertise is undefined
data.expertise.scoredTaskCountnumberTasks carrying both automation and expertise scores
data.expertise.methodstringHow the numbers are produced (Autor & Thompson 2025, Table 8 coefficients)
data.expertise.caveatstringOut-of-sample disclosure: the coefficients were estimated on 1980-2018 computerization, and applying them to AI-era exposure is a transfer. Shipped in the payload because the site disclosures it too
data.expertise.distributionVintagestringBuild date and career count of the percentile distribution, e.g. "2026-09-29 (928 careers)". Percentiles can shift when the distribution is rebuilt after each quarterly rescoring

expertise.bands

FieldTypeDescription
data.expertise.bandsobjectKeyed by band id (entry, mid, senior). All three by default; just one when ?band= is passed. Bands are relative to each career: entry = the career's least-expert third of tasks, senior = the top third
...bands.*.labelstring"Entry", "Mid", or "Senior"
...bands.*.personalExposurenumberWeighted avg automation likelihood over the band's task portfolio (its tercile plus everything below it), 0-1
...bands.*.careerAvgExposurenumberWeighted avg automation likelihood over all scored tasks, for comparison
...bands.*.rungErosionnumberWeighted share of the band's defining tasks at/past the automation threshold, 0-1
...bands.*.bandOutlookModifiernumberPositive = this band's outlook is better than the career's headline number; negative = worse
...bands.*.sentimentstring"positive", "neutral", or "negative" — the same verdict the career page's Experience Outlook badge shows
...bands.*.definingTaskCountnumberNumber of tasks in the band's defining tercile

laborMarket

BLS employment and wage data. Employment counts are absolute (not in thousands).

FieldTypeDescription
data.laborMarket.medianWagenumber | stringAnnual median wage in USD. BLS OEWS national median where published (the same figure shown on career pages); falls back to the Employment Projections wage, which can be a capped string like ">= $239,200"
data.laborMarket.medianWageSourcestringWhere medianWage came from: "oews_national" or "employment_projections" (fallback)
data.laborMarket.employment2024numberTotal jobs in 2024
data.laborMarket.employment2034numberProjected total jobs in 2034
data.laborMarket.employmentChangePctBLSnumberProjected % change in employment 2025-2035
data.laborMarket.annualOpeningsBLSnumberProjected average annual openings
data.laborMarket.educationRequiredstringTypical entry-level education
data.laborMarket.experienceRequiredstringRequired work experience
data.laborMarket.trainingRequiredstringOn-the-job training requirements
data.laborMarket.dataSourcestringHow the Employment Projections fields (employment, openings, education, experience, training) were joined: "direct", "mapped_via_crosswalk", "aggregated_from_children", or "inherited_from_parent"

local (Local Picture — added in v1.1)

Metro/nonmetro wage and employment for the occupation, from BLS OEWS. Populated when the request passes ?area= or ?county=. For the full per-area table, use the Local Areas Endpoint.

FieldTypeDescription
data.localobjectWithout ?area= or ?county=, just { available, vintage } — available says whether OEWS publishes this occupation, so you know whether asking for an area will return data. With a location param, the full block below
data.local.areaobjectThe resolved area: code, title, state, type ("metro" or "nonmetro")
data.local.workersnumberTotal employment for this occupation in the area. null = BLS-suppressed, which is meaningful — never coerced to zero
data.local.medianWagenumberAnnual median wage in the area, USD
data.local.locationQuotientnumberOccupation concentration vs the nation (1.0 = same share of local jobs as nationally)
data.local.nationalobjectNational workers and medianWage for comparison (BLS-published national figures, not an average of areas)
data.local.vintagestringOEWS release the numbers come from, e.g. "May 2025 OEWS"

hierarchy

SOC hierarchy relationships. Each reference is a minimal {code, name, slug, url} object.

FieldTypeDescription
data.hierarchy.parents.majorobjectSOC Major Group parent
data.hierarchy.parents.minorobjectSOC Minor Group parent
data.hierarchy.parents.broadobjectSOC Broad Occupation parent
data.hierarchy.siblingsobject[]Related careers sharing the same parent and level
data.hierarchy.childrenobject[]Direct children. Empty for detailed-level occupations.

Example Response

{
  "success": true,
  "data": {
    "code": "15-1252.00",
    "name": "Software Developers",
    "nameShort": "Software Developers",
    "slug": "software-developers",
    "level": "detailed",
    "description": "Develop, create, and modify general computer applications software...",
    "url": "https://www.airesilience.org/career/software-developers",
    "aiResilience": {
      "score": 0.62,
      "label": "Mostly Resilient",
      "confidence": "High",
      "confidenceScore": 82,
      "explanation": "Software developers..."
    },
    "airm_cv": {
      "version": "v1.5",
      "percentile": 0.45,
      "label": "Medium",
      "rawScore": 0.52
    },
    "sources": {
      "anthropic":      { "percentile": 0.42, "rawScore": 0.18 },
      "microsoft":      { "percentile": 0.38, "rawScore": 0.45 },
      "wrtmj":          { "percentile": 0.55, "label": "Medium", "rawRiskPercent": "65", "growth": "...", "volume": "..." },
      "openai":         { "percentile": 0.47, "rawScore": 0.0038 },
      "althoff":        { "wageBillPercentile": 0.61, "rawScore": 0.74 },
      "manning":        { "adaptiveCapacityPercentile": 0.58, "adaptiveCapacityRawScore": 0.63 },
      "lted_blsOpportunity": { "score": 0.7, "label": "High" }
    },
    "subscores": {
      "meaningfulHumanContribution":  { "score": 0.65, "label": "High" },
      "sustainedEconomicOpportunity": { "score": 0.70, "label": "High" }
    },
    "stepsToTake": [
      "Build a portfolio of projects that show end-to-end problem solving...",
      "Develop fluency with AI-assisted coding tools..."
    ],
    "tasks": [
      {
        "id": "1",
        "task": "Confer with systems analysts, engineers, programmers and others...",
        "taskType": "Core",
        "automationLikelihood": 0.18,
        "resilienceScore": 0.82,
        "expertiseLevel": 0.55,
        "analysisDate": "2026-05-16"
      }
    ],
    "expertise": {
      "deltaExpertise": 0.0215,
      "deltaExpertisePercentile": 79,
      "routine": { "resilience": 0.42, "erosion": 0.55 },
      "expert":  { "resilience": 0.71, "erosion": 0.12 },
      "forecast": {
        "wage":       { "center": 1.8,  "low": 0.9,  "high": 2.7 },
        "employment": { "center": -2.7, "low": -3.4, "high": -2.0 },
        "unit": "percentage points per decade vs the average occupation",
        "capped": false
      },
      "bands": {
        "entry":  { "label": "Entry",  "personalExposure": 0.58, "careerAvgExposure": 0.44, "rungErosion": 0.67, "bandOutlookModifier": -0.043, "sentiment": "negative", "definingTaskCount": 6 },
        "mid":    { "label": "Mid",    "personalExposure": 0.49, "careerAvgExposure": 0.44, "rungErosion": 0.33, "bandOutlookModifier": -0.021, "sentiment": "negative", "definingTaskCount": 6 },
        "senior": { "label": "Senior", "personalExposure": 0.41, "careerAvgExposure": 0.44, "rungErosion": 0.17, "bandOutlookModifier": 0.043,  "sentiment": "positive", "definingTaskCount": 6 }
      },
      "scoredTaskCount": 18,
      "method": "Autor & Thompson (2025) Table 8 coefficients applied to task-level automation and expertise scores",
      "caveat": "Coefficients were estimated on 1980-2018 computerization. Applying them to AI-era exposure is an out-of-sample transfer.",
      "distributionVintage": "2026-09-29 (928 careers)"
    },
    "laborMarket": {
      "medianWage": 135980,
      "medianWageSource": "oews_national",
      "employment2024": 1656000,
      "employment2034": 1800000,
      "employmentChangePctBLS": 8.7,
      "annualOpeningsBLS": 140100,
      "educationRequired": "Bachelor's degree",
      "experienceRequired": "None",
      "trainingRequired": "None",
      "dataSource": "direct"
    },
    "local": {
      "area": { "code": "14460", "title": "Boston-Cambridge-Newton, MA-NH", "state": "MA", "type": "metro" },
      "workers": 42310,
      "medianWage": 166090,
      "locationQuotient": 1.44,
      "national": { "workers": 1687890, "medianWage": 135980 },
      "vintage": "May 2025 OEWS"
    },
    "hierarchy": {
      "parents": {
        "major": { "code": "15-0000", "name": "Computer and Mathematical Occupations", "slug": "computer-and-mathematical-occupations", "url": "https://www.airesilience.org/career/computer-and-mathematical-occupations" },
        "minor": { "code": "15-1200", "name": "Computer Occupations", "slug": "computer-occupations", "url": "https://www.airesilience.org/career/computer-occupations" },
        "broad": { "code": "15-1250", "name": "Software and Web Developers, Programmers, and Testers", "slug": "software-and-web-developers-programmers-and-testers", "url": "https://www.airesilience.org/career/software-and-web-developers-programmers-and-testers" }
      },
      "siblings": [
        { "code": "15-1253.00", "name": "Software Quality Assurance Analysts and Testers", "slug": "software-quality-assurance-analysts-and-testers", "url": "https://www.airesilience.org/career/software-quality-assurance-analysts-and-testers" }
      ],
      "children": []
    },
    "lastUpdated": "2026-05-16"
  }
}

Bulk (List) Endpoint

Returns a summary list of all occupations. Useful for syncing the dataset or building filtered views client-side. Each entry is a compact summary (resilience score, label, confidence) — for the full per-occupation payload, call the single-career endpoint with the SOC code.

GET https://www.airesilience.org/ext/api/careers

Query Parameters

All parameters are optional. When neither page nor pageSize is supplied, the endpoint returns the full unpaginated list.

ParameterTypeDescription
pageinteger1-indexed page number. Triggers paginated response.
pageSizeintegerItems per page. Default 100, max 500. Triggers paginated response.
levelstringFilter by SOC hierarchy level: major, minor, broad, detailed.
labelstringFilter by resilience label. One of the 6 labels (URL-encode spaces): "Highly Resilient", "Resilient", "Mostly Resilient", "Somewhat Resilient", "Not Very Resilient", "Vulnerable".

Response Fields

FieldTypeDescription
data[]object[]Array of career summaries, sorted by SOC code ascending
data[].codestringSOC code
data[].namestringCareer name
data[].slugstringURL slug
data[].levelstringSOC hierarchy level
data[].urlstringLink to the career report page
data[].aiResilience.scorenumberCombined AI resilience score (0-1, higher = more resilient)
data[].aiResilience.labelstringOne of the 6 resilience labels
data[].aiResilience.confidencestringConfidence level
meta.totalnumberTotal matching careers after filters
meta.lastUpdatedstringDate (YYYY-MM-DD) of the latest data snapshot
meta.pagenumberPaginated responses only
meta.pageSizenumberPaginated responses only
meta.totalPagesnumberPaginated responses only
meta.hasMorebooleanPaginated responses only. True if more pages exist.

Example Response (paginated)

GET /ext/api/careers?level=detailed&page=1&pageSize=2

{
  "success": true,
  "data": [
    {
      "code": "11-1011.00",
      "name": "Chief Executives",
      "slug": "chief-executives",
      "level": "detailed",
      "url": "https://www.airesilience.org/career/chief-executives",
      "aiResilience": {
        "score": 0.78,
        "label": "Resilient",
        "confidence": "High"
      }
    },
    {
      "code": "11-1021.00",
      "name": "General and Operations Managers",
      "slug": "general-and-operations-managers",
      "level": "detailed",
      "url": "https://www.airesilience.org/career/general-and-operations-managers",
      "aiResilience": {
        "score": 0.61,
        "label": "Mostly Resilient",
        "confidence": "Medium-high"
      }
    }
  ],
  "meta": {
    "total": 867,
    "page": 1,
    "pageSize": 2,
    "totalPages": 434,
    "hasMore": true,
    "lastUpdated": "2026-05-16"
  }
}

Search Endpoint

Search occupations by title keyword. Returns the same summary shape as the bulk endpoint, ranked by where the match occurs (earlier in the title = higher rank).

GET https://www.airesilience.org/ext/api/careers/search?q={keyword}

Query Parameters

ParameterTypeDescription
qstringRequired. Search keyword (min 2 chars). Case-insensitive substring match against career name and short name.
limitintegerMax results. Default 50, max 200.
levelstringOptional filter by SOC level: major, minor, broad, detailed.

Example Response

GET /ext/api/careers/search?q=software&limit=2

{
  "success": true,
  "data": [
    {
      "code": "15-1252.00",
      "name": "Software Developers",
      "slug": "software-developers",
      "level": "detailed",
      "url": "https://www.airesilience.org/career/software-developers",
      "aiResilience": { "score": 0.62, "label": "Mostly Resilient", "confidence": "High" }
    },
    {
      "code": "15-1253.00",
      "name": "Software Quality Assurance Analysts and Testers",
      "slug": "software-quality-assurance-analysts-and-testers",
      "level": "detailed",
      "url": "https://www.airesilience.org/career/software-quality-assurance-analysts-and-testers",
      "aiResilience": { "score": 0.58, "label": "Mostly Resilient", "confidence": "Medium-high" }
    }
  ],
  "meta": {
    "query": "software",
    "total": 7,
    "limit": 2,
    "truncated": true,
    "lastUpdated": "2026-05-16"
  }
}

Tasks Endpoint

Tasks-only view of a single occupation. Returns the same tasks array as the single-career endpoint, plus minimal occupation identity. Useful when you only need task-level resilience scores and want a smaller payload.

GET https://www.airesilience.org/ext/api/career/{code}/tasks

Example Response

GET /ext/api/career/15-1252.00/tasks

{
  "success": true,
  "data": {
    "code": "15-1252.00",
    "name": "Software Developers",
    "slug": "software-developers",
    "level": "detailed",
    "url": "https://www.airesilience.org/career/software-developers",
    "tasks": [
      {
        "id": "1",
        "task": "Confer with systems analysts, engineers, programmers and others...",
        "taskType": "Core",
        "automationLikelihood": 0.18,
        "resilienceScore": 0.82,
        "expertiseLevel": 0.55,
        "analysisDate": "2026-05-16"
      }
    ]
  }
}

Report Endpoint

The narrative "Career Report" for an occupation — the written analysis shown on the career page. Returns an ordered array of content sections: the AI resilience summary, the deep-research analysis paragraphs, the AI replacement verdict, and suggested actions. Section content is markdown-formatted text.

GET https://www.airesilience.org/ext/api/career/{code}/report

Response Fields

Alongside the occupation identity (code, name, slug, level, reportUrl), the content lives in data.careerReport, an ordered array of sections.

FieldTypeDescription
data.careerReport[].typestringSection type: "Summary", "resilienceParagraph", "replacementVerdict", or "suggestedActions"
data.careerReport[].titlestringDisplay heading for the section
data.careerReport[].contentstringSection body as markdown-formatted text

Example Response

GET /ext/api/career/15-1252.00/report

{
  "success": true,
  "data": {
    "code": "15-1252.00",
    "name": "Software Developers",
    "slug": "software-developers",
    "level": "detailed",
    "reportUrl": "https://www.airesilience.org/career/software-developers",
    "careerReport": [
      {
        "type": "Summary",
        "title": "AI Resilience Summary",
        "content": "Software developers are mostly resilient to AI impacts..."
      },
      {
        "type": "resilienceParagraph",
        "title": "How is AI changing Software Developers jobs?",
        "content": "How is AI changing Software Developers jobs?\n\nRight now, AI in software development is leaning much more toward augmentation than full automation..."
      },
      {
        "type": "replacementVerdict",
        "title": "AI Replacement Verdict",
        "content": "Will AI replace software developers? Not in the near term..."
      },
      {
        "type": "suggestedActions",
        "title": "Suggested Actions",
        "content": "- Build a portfolio of end-to-end projects...\n- Develop fluency with AI-assisted coding tools..."
      }
    ]
  }
}

Local Areas Endpoint

The full per-area table for one occupation: every metro and nonmetro area's workers, median annual wage, and location quotient, plus the national figures. Same BLS OEWS data as the local block on the single-career endpoint, all ~530 areas at once. Detailed occupation codes resolve to their OEWS occupation (combined-occupation alias or SOC broad group where needed); aggregate SOC levels and military occupations return 404 GEO_NOT_AVAILABLE. Suppressed BLS values are null, never zero.

GET https://www.airesilience.org/ext/api/career/{code}/local

Query Parameters

All parameters are optional.

ParameterTypeDescription
typestringFilter to metro or nonmetro areas
statestringFilter to one state by two-letter abbreviation, e.g. MA
sortstringlq (default), workers, or medianWage. Always descending, suppressed values last

Example Response

GET /ext/api/career/15-1252.00/local?state=MA&sort=workers

{
  "success": true,
  "data": {
    "code": "15-1252.00",
    "occCode": "15-1252",
    "title": "Software Developers",
    "national": { "workers": 1687890, "medianWage": 135980 },
    "areaCount": 5,
    "areas": [
      {
        "code": "14460",
        "title": "Boston-Cambridge-Newton, MA-NH",
        "state": "MA",
        "type": "metro",
        "workers": 42310,
        "medianWage": 166090,
        "locationQuotient": 1.44
      },
      {
        "code": "49340",
        "title": "Worcester, MA-CT",
        "state": "MA",
        "type": "metro",
        "workers": 4160,
        "medianWage": 139560,
        "locationQuotient": 0.71
      }
    ],
    "vintage": "May 2025 OEWS"
  }
}

Area Search Endpoint

Area discovery: how a consumer goes from a place name like "boston" to the area ID the career endpoints take as ?area=. With no parameters it returns the full directory of ~530 OEWS areas. The list changes once a year with the OEWS release, so responses cache hard.

GET https://www.airesilience.org/ext/api/geo/areas

Query Parameters

All parameters are optional.

ParameterTypeDescription
qstringName search over ~32k US places and the area titles themselves, ranked the same way the site's location dropdown ranks them. Supports "name" or "name, ST" (e.g. boston, ma). Each hit includes matchedPlace showing which place matched
countystringResolve a 5-digit county GEOID to its one containing area. Mutually exclusive with q
typestringFilter to metro or nonmetro areas
statestringFilter to one state by two-letter abbreviation

Example Response

GET /ext/api/geo/areas?q=boston, ma

{
  "success": true,
  "data": {
    "areas": [
      {
        "code": "14460",
        "title": "Boston-Cambridge-Newton, MA-NH",
        "state": "MA",
        "type": "metro",
        "matchedPlace": "Boston, MA"
      }
    ],
    "count": 1,
    "vintage": "May 2025 OEWS"
  }
}

Error Responses

StatusCodeDescription
400INVALID_SOC_CODESOC code doesn't match expected format
400INVALID_LEVELBulk endpoint: level must be one of major, minor, broad, detailed
400INVALID_LABELBulk endpoint: label must be one of the 6 resilience labels
400INVALID_PAGEBulk endpoint: page must be a positive integer (1-indexed)
400INVALID_PAGE_SIZEBulk endpoint: pageSize must be between 1 and 500
400INVALID_QUERYSearch endpoint: q is required and must be at least 2 characters
400INVALID_LIMITSearch endpoint: limit must be between 1 and 200
400INVALID_BANDBad band value — expected entry, mid, or senior
400INVALID_AREAUnknown OEWS area ID — list valid IDs via the Area Search Endpoint
400AMBIGUOUS_LOCATIONMutually exclusive location params passed together (area + county, or q + county)
400INVALID_TYPEBad type value — expected metro or nonmetro
400INVALID_SORTBad sort value — expected lq, workers, or medianWage
404CAREER_NOT_FOUNDNo career exists for the given SOC code
404COUNTY_NOT_FOUNDNo OEWS area for the given county GEOID
404GEO_NOT_AVAILABLEOEWS does not publish area data for the occupation (aggregate SOC levels, military)
429RATE_LIMITEDExceeded 100 requests/minute. Includes Retry-After header.

Rate Limiting

The API is rate limited to 100 requests per minute per IP address using a sliding window. If you hit the limit, you'll receive a 429 response with a Retry-After header indicating how many seconds to wait.

CORS

This API supports cross-origin requests from any domain. You can call it directly from browser-based applications without a proxy.

MCP Server for AI Assistants

We provide a Model Context Protocol (MCP) server that wraps this API, allowing AI assistants like Claude to look up career resilience data directly. No API key required.

Install via npm: ai-resilience-mcp

Configuration

Add the following to your MCP client configuration:

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "ai-resilience": {
      "command": "npx",
      "args": ["-y", "ai-resilience-mcp"]
    }
  }
}

Claude Code

Add to your project's .mcp.json:

{
  "mcpServers": {
    "ai-resilience": {
      "command": "npx",
      "args": ["-y", "ai-resilience-mcp"]
    }
  }
}

Available Tools

ToolInputDescription
lookup_careercode (SOC code); optional area, county, bandReturns the career payload: AI resilience score, label, confidence, explanation, AIRM data (airm_cv), the experience outlook, and — with an area or county — the local wage/employment picture
search_areasq (place name)Finds the OEWS area ID for a place name ("boston" → Boston-Cambridge-Newton, MA-NH), for use as area in the other tools
lookup_localcode; optional type, state, sort, limitFull per-area wage and employment table for one occupation (workers, median wage, location quotient by metro/nonmetro area)

Changelog

Notable changes to the API. Breaking changes are called out explicitly.

2026-09-16

API v2.1

The geo ("Local Picture") and expertise ("Experience Outlook") layers. Everything is additive on top of v2.0 — no existing field changed — so this bumps the minor per the policy below.

  • Single-career endpoint: new ?area= and ?county= params add a data.local block (workers, median wage, location quotient, national comparison) for one metro or nonmetro area.
  • Added GET /ext/api/career/{code}/local — the full per-area table for one occupation, with type, state, and sort filters.
  • Added GET /ext/api/geo/areas — area directory, name search (?q=), and county-GEOID resolution (?county=).
  • Task rows on the single-career and tasks endpoints gain expertiseLevel.
  • Single-career endpoint: new data.expertise block (ΔExpertise score and percentile, routine vs expert resilience and erosion, ten-year wage/employment forecast with bounds and out-of-sample caveat, per-band outlooks). Optional ?band=entry|mid|senior narrows the bands map.
  • Added the geo dataset CSV: GET /ext/api/dataset-geo.csv (one row per occupation per area; the main dataset.csv is unchanged).
  • X-API-Version is now also sent by the dataset routes, which had been missing it despite the 2026-05-26 note saying it is on all responses.
  • The attribution object gains a sources array crediting BLS OEWS (May 2025) and Autor & Thompson (2025).
  • New error codes: INVALID_BAND, INVALID_AREA, AMBIGUOUS_LOCATION, COUNTY_NOT_FOUND, INVALID_TYPE, INVALID_SORT, GEO_NOT_AVAILABLE.

2026-08-25

field renamesv2.0

Breaking: several response fields were renamed so the name says which source or subscore the value belongs to. Values are unchanged; only the keys moved. Update any client reading the old names.

  • data.airm → data.airm_cv (all child fields unchanged)
  • data.sources.blsOpportunity → data.sources.lted_blsOpportunity
  • data.sources.wrtmj.riskPercent → data.sources.wrtmj.rawRiskPercent
  • data.sources.manning.rawScore → data.sources.manning.adaptiveCapacityRawScore
  • data.laborMarket.employmentChangePct → data.laborMarket.employmentChangePctBLS
  • data.laborMarket.annualOpenings → data.laborMarket.annualOpeningsBLS
  • Fixed data.airm_cv.version, which reported "v0.1"; it now correctly reports the model version, "v1.5".
  • Dataset CSV: removed the bls_percentile and bls_opportunityScore columns. Both duplicated ltedScore, which remains.

2026-08-21

raw scores + confidence scorev1.5

The single-career endpoint now exposes every field in the downloadable dataset CSV. Additive and backward compatible. Also corrects X-API-Version, which had stayed at 1.0 through the four additive releases above; it now reports 1.5 and earlier entries carry the version they should have shipped with.

  • Added data.aiResilience.confidenceScore — the 0-100 numeric score behind the existing confidence level.
  • Added data.sources.althoff.rawScore and data.sources.manning.rawScore alongside their existing percentiles. Null where the source does not cover the career.

2026-08-03

openai signalsv1.4

Added the OpenAI Signals AI-exposure source. Additive and backward compatible. (Logged retroactively.)

  • Added data.sources.openai with percentile and rawScore. Both null where the source does not cover the career.
  • Added openai_percentile and openai_raw columns to the dataset CSV download.

2026-07-30

attribution objectv1.3

Every successful response now includes a top-level attribution object carrying the CC BY 4.0 credit text, canonical URL, and license link. Additive and backward compatible: no existing field changed, so clients reading data or meta are unaffected.

2026-06-22

report endpointv1.2

Added the narrative career-report endpoint.

  • Added GET /ext/api/career/{code}/report. Returns the written career report as an ordered careerReport array of { type, title, content } sections.
  • Section types: Summary, resilienceParagraph (analysis Q&A), replacementVerdict, and suggestedActions. Content is markdown-formatted text.

2026-06-09

search + tasks endpointsv1.1

Two new endpoints plus internal usage analytics.

  • Added GET /ext/api/careers/search?q=. Title/keyword search. Supports limit (default 50, max 200) and level filter. Returns the same summary shape as the bulk endpoint.
  • Added GET /ext/api/career/{code}/tasks. Tasks-only view of an occupation, smaller payload than the full single-career endpoint.
  • New 400 error codes: INVALID_QUERY, INVALID_LIMIT.
  • Internal: per-endpoint usage counters now tracked in Upstash Redis. MCP traffic is bucketed separately via the User-Agent header (ai-resilience-mcp). No user-visible change.

2026-05-26

bulk endpointv1.0

Added a new bulk (list) endpoint: GET /ext/api/careers. Returns summary entries (code, name, slug, level, url, resilience score/label/confidence) for all occupations.

  • Optional filters: ?level= and ?label=.
  • Optional pagination: ?page=N&pageSize=N (default 100, max 500). When neither is supplied, returns the full unpaginated list.
  • New 400 error codes: INVALID_LEVEL, INVALID_LABEL, INVALID_PAGE, INVALID_PAGE_SIZE.

2026-05-26

API v1.0

Formally declared the REST API contract version as v1.0. This is distinct from the AI Resilience Model version (data.airm.version), which remains at v1.5.

  • Added an X-API-Version response header on all responses so clients can detect the contract version without parsing the body.
  • Breaking changes to the REST contract will bump the major version (v2.0, v3.0, etc.); additive changes will bump the minor.

2026-05-26

expanded response

Significantly expanded the response with additional data exposed from the site. All previously-existing fields are unchanged.

  • Added data.sources with per-source signals (Anthropic, Microsoft, WRTMJ, Althoff, Manning, BLS opportunity).
  • Added data.subscores (meaningful human contribution, sustained economic opportunity).
  • Added data.stepsToTake — AI-generated suggested actions for students.
  • Added data.tasks with task-level automation likelihood / resilience scores (detailed occupations only).
  • Added data.laborMarket with BLS employment, wage, education, and experience data.
  • Added data.hierarchy (parents, siblings, children) for navigating the SOC tree.
  • Added data.lastUpdated, data.nameShort, data.slug, data.level, and data.description.

2026-05-26

model v1.5 (airm)
  • Breaking: Renamed data.cvModel to data.airm in the response.
  • Added data.airm.version field reporting the AI Resilience Model version.

Questions? Contact us at air@careervillage.org.

Share your feedback

The AI Resilience Report is a project from CareerVillage.org®, a registered 501(c)(3) nonprofit.

Built with ❤️ by Sandbox Web

The AI Resilience Report is governed by CareerVillage.org’s Privacy Policy and Terms of Service. This site is not affiliated with Anthropic, Microsoft, or any other data provider and doesn't necessarily represent their viewpoints. This site is being actively updated, and may sometimes contain errors or require improvement in wording or data. To report an error or request a change, please contact air@careervillage.org.