Skip to main content

The Ayla public API

Every number on this site comes from the JSON endpoints below. They are read-only, need no key, and cover the job postings Ayla collects from 640+ official sources (the record starts 2025-12-07) and the OPM federal workforce data behind the analytics and occupation pages. Published 2026-09-15, last changed 2026-09-15.

How to call it

  • Base URL https://aylagov.com/api. Every response is JSON. No authentication, no key, no cookie.
  • Limits: 120 requests per minute per IP address on the job and map endpoints, 30 per minute on the analytics and workforce endpoints. Over the limit you get HTTP 429; wait and retry.
  • Search results are paged: page starts at 0 and limit caps at 100. Read pagination.total for the count.
  • A wrong parameter name returns HTTP 400 with the offending property named, so a typo never silently returns everything.
  • Responses carry X-Robots-Tag: noindex. Link to the page you took a figure from, not to the endpoint.

Job postings

The live board. A job record carries id, title, agency, city, stateCode, locationText, salaryMin, salaryMax, salaryText, salaryType, workArrangement, jobType, category, seniorityLevel, requiresCitizenship, skills, postedDate, closeDate, sourceUrl, organizationType and sector. The page for a posting is https://aylagov.com/jobs/<slug>/<id>; any slug redirects to the right one.

EndpointWhat it returnsParameters
GET /jobs/searchSearch the live postings. Returns jobs, pagination and two facets.search (keywords), page (0-based), limit (1 to 100, default 20), sortBy (quality, newest, highest_paying, closing_soon, remote_first), filters (a JSON object, URL-encoded; keys below).
GET /jobs/job/:idOne posting by its UUID, including the description and the employer apply link.None.
GET /jobs/filtersThe vocabulary the search accepts: states with counts, categories, organization types, seniority levels, benefits, sectors.None.
GET /jobs/suggestTitle suggestions for a partial query.q (2 or more characters).

Keys inside filters

filters is one JSON object passed as a URL-encoded query parameter. Send only the keys you need.

state
Two-letter code, for example "TX".
category
A category slug from /jobs/filters, for example "healthcare" or "it-technology".
organizationType
federal, state, county, city, school_district, university, health_system, contractor, nonprofit.
workArrangement
An object of flags: {"remote":"yes","hybrid":"yes","onSite":"yes"}. Include only the ones you want.
salary
An object: {"min":100000,"max":200000}. Annualised pay; hourly postings are normalised.
seniorityLevel
entry, mid, senior, supervisor, executive.
agency
Employer name as it appears in the results, matched exactly.
location
City or place name, matched against the posting location text.
closeDate
"closing-soon" (closes within 7 days) or "open".
curl -G "https://aylagov.com/api/jobs/search" \
  --data-urlencode "search=data scientist" \
  --data-urlencode "limit=10" \
  --data-urlencode 'filters={"state":"VA","organizationType":"contractor","salary":{"min":120000}}'

Map and regions

EndpointWhat it returnsParameters
GET /map/statsJob counts and average pay per region.level (state, county, city, zip; required), state (narrows county, city and zip levels).
GET /map/regions/:type/:code/insightsOne region in depth: totals, top employers, categories, pay distribution, recent postings.type is state, county, city or zip; code is the state code, county name, city name or ZIP.
GET /map/jobsGeocoded postings for a map view.state, city, zipCode, category, organizationType, workArrangement, salaryMin, salaryMax, limit (default 100), offset, or a bounding box (minLng, minLat, maxLng, maxLat).
GET /map/clustersPoint clusters for a bounding box.minLng, minLat, maxLng, maxLat (required), precision (clustering precision 1 to 4, default 2).

Market analytics

Aggregates over the live postings. Each response has a generatedAt timestamp; quote it with the number. Pay figures use annualised salary, so hourly and annual postings are comparable.

EndpointWhat it returnsParameters
GET /analytics/memoThe one-call summary: coverage, record size, employer-type mix, top employers, top states, top functions, pay.None.
GET /analytics/market-overviewPostings by organization type, work arrangement, top states and top agencies.startDate, endDate (ISO dates, optional).
GET /analytics/salary-insightsPay bands, pay by state and pay by organization type.None.
GET /analytics/salary-distributionPercentiles for one role.role (required), state, orgType.
GET /analytics/trendingEmployers and locations with the fastest-growing posting counts.None.

Federal workforce

OPM Federal Workforce Data, loaded monthly. Every response names the month the data runs through (dataThrough) and the snapshot used for headcount. Where OPM redacts a state or agency, the redacted count is returned rather than guessed.

EndpointWhat it returnsParameters
GET /workforce/overviewFederal civilian headcount, hires and separations over the last 12 months, and the month the data runs through.None.
GET /workforce/agenciesHeadcount, average pay, hires and separations per agency.months (window, default 12).
GET /workforce/seriesThe same by OPM occupational series.months.
GET /workforce/statesFederal headcount by state, with the redacted count disclosed.None.
GET /workforce/signalsAgencies hiring and separating the most for one series or state.series (4-digit code), state, months.
GET /workforce/role-reportThe role report: who is hiring a role, what they advertise, and the federal flow for the mapped series.series (comma-separated 4-digit codes, up to 40), titles (comma-separated, up to 8), months, agency (OPM agency code), states (comma-separated), employer, metro. At least one of series or agency is required.

MCP server for AI agents

The same data is available to agents over the Model Context Protocol. The endpoint is https://aylagov.com/api/mcp, Streamable HTTP transport, JSON-RPC 2.0, stateless: POST one request or a batch and read the JSON reply. There is no session, no SSE stream and no authentication. Tools:

  • search_jobs: query, state, category, organization_type, work_arrangement, salary_min, seniority, sort, page, limit.
  • get_job: id.
  • suggest_titles: query.
  • role_report: series, titles, months, agency, states, employer.
  • federal_workforce: months.
  • market_overview: no arguments.
curl -X POST "https://aylagov.com/api/mcp" -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": { "name": "search_jobs",
              "arguments": { "query": "epidemiologist", "state": "MD", "limit": 5 } }
}'

Feeds and machine files

  • /sitemap.xml: the sitemap index; job URLs are split across the sitemap-jobs files it lists.
  • /government-hiring-report/feed.xml: RSS for the Government Hiring Report.
  • /llms.txt: a plain-text map of the site for language models, and the agent policy for what crawlers and agents may do here.
  • IndexNow is supported: new and retired job URLs are submitted daily.

Terms

  • The API is free for research, journalism, personal projects and internal use inside an organization, within the rate limits above.
  • Cite Ayla when you publish a figure: “Ayla (aylagov.com), retrieved on the date”. A link to the page the number appears on is preferred to a link to the endpoint.
  • Do not republish the listings as a competing job board, and do not resell the data. For bulk access, a licence or a data feed, write to hello@aylagov.com.
  • Postings are collected from the employers’ own systems and can lag them. Apply on the employer site the record links to; Ayla does not take applications. There is no uptime guarantee and response shapes can change; this page is updated when they do.
  • The endpoints under /api that are not listed here serve the signed-in product and are not public.