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:
pagestarts at 0 andlimitcaps at 100. Readpagination.totalfor 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.
| Endpoint | What it returns | Parameters |
|---|---|---|
GET /jobs/search | Search 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/:id | One posting by its UUID, including the description and the employer apply link. | None. |
GET /jobs/filters | The vocabulary the search accepts: states with counts, categories, organization types, seniority levels, benefits, sectors. | None. |
GET /jobs/suggest | Title 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
| Endpoint | What it returns | Parameters |
|---|---|---|
GET /map/stats | Job counts and average pay per region. | level (state, county, city, zip; required), state (narrows county, city and zip levels). |
GET /map/regions/:type/:code/insights | One 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/jobs | Geocoded 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/clusters | Point 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.
| Endpoint | What it returns | Parameters |
|---|---|---|
GET /analytics/memo | The one-call summary: coverage, record size, employer-type mix, top employers, top states, top functions, pay. | None. |
GET /analytics/market-overview | Postings by organization type, work arrangement, top states and top agencies. | startDate, endDate (ISO dates, optional). |
GET /analytics/salary-insights | Pay bands, pay by state and pay by organization type. | None. |
GET /analytics/salary-distribution | Percentiles for one role. | role (required), state, orgType. |
GET /analytics/trending | Employers 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.
| Endpoint | What it returns | Parameters |
|---|---|---|
GET /workforce/overview | Federal civilian headcount, hires and separations over the last 12 months, and the month the data runs through. | None. |
GET /workforce/agencies | Headcount, average pay, hires and separations per agency. | months (window, default 12). |
GET /workforce/series | The same by OPM occupational series. | months. |
GET /workforce/states | Federal headcount by state, with the redacted count disclosed. | None. |
GET /workforce/signals | Agencies hiring and separating the most for one series or state. | series (4-digit code), state, months. |
GET /workforce/role-report | The 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.