{"openapi":"3.1.0","info":{"title":"Job Risk Index API","description":"\nJob Risk Index — Public data API for LLMs and agents.\n\nServes the SAME data already published on jobriskindex.com (professions,\nskills, salaries, city demand, trends and profiles) as JSON, protected only\nby a per-IP rate limit. Public aggregated data only: never raw data,\nprovenance, source files or internal pipeline processes (ADR-006/0012).\n\n## Public routes\n\nIn production, Caddy serves this API under `/api` (`handle_path /api/*`), so\nthe public URLs are:\n\n- OpenAPI docs: `/api/docs` (UI) and `/api/openapi.json`\n- Data API: `/api/v1/professions`, `/api/v1/professions/{id}`,\n  `/api/v1/skills`, `/api/v1/skills/{slug}`, `/api/v1/salaries`,\n  `/api/v1/cities`, `/api/v1/trends`, `/api/v1/search?q=…`, `/api/v1/meta`\n\n## Rate limit\n\n- **10 requests/hour per IP** (global across `/api/v1`, no auth).\n- `429` response with `X-RateLimit-Limit`, `X-RateLimit-Remaining` and\n  `Retry-After` (seconds).\n- `/api/docs`, `/api/openapi.json` and `/health` do NOT count; the CORS\n  preflight (`OPTIONS`) does not count either.\n- The IP is stored only as a hash (sha256), never raw.\n\n## Examples\n\n```bash\ncurl https://jobriskindex.com/api/v1/professions?limit=5\ncurl https://jobriskindex.com/api/v1/professions/accountant\ncurl https://jobriskindex.com/api/v1/skills\ncurl https://jobriskindex.com/api/v1/skills/python\ncurl https://jobriskindex.com/api/v1/salaries\ncurl https://jobriskindex.com/api/v1/cities\ncurl https://jobriskindex.com/api/v1/trends\ncurl \"https://jobriskindex.com/api/v1/search?q=data%20analyst\"\ncurl https://jobriskindex.com/api/v1/meta\n```\n","version":"0.1.0"},"paths":{"/api/v1/professions":{"get":{"tags":["Public API"],"summary":"List Professions","description":"Paginated summary list of professions in the canonical index order\n(risk_score desc, id asc). limit/offset pagination (limit max 50).\n\nExample: `curl https://jobriskindex.com/api/v1/professions?limit=10&offset=0`","operationId":"list_professions_api_v1_professions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Maximum 50 per page.","default":20,"title":"Limit"},"description":"Maximum 50 per page."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/professions/{profession_id}":{"get":{"tags":["Public API"],"summary":"Get Profession","description":"Full public profile of one profession — the same shape as\nprofessions.json (title/aliases/risk/timeline/salary/skills/entry_route/\nfaqs/sources) WITHOUT internal fields (job_query, skills_source, trend\nprovenance) and with the public URL of the profile.\n\nExample: `curl https://jobriskindex.com/api/v1/professions/accountant`","operationId":"get_profession_api_v1_professions__profession_id__get","parameters":[{"name":"profession_id","in":"path","required":true,"schema":{"type":"string","title":"Profession Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/skills":{"get":{"tags":["Public API"],"summary":"List Skills","description":"Skills catalog (build ∪ enter across all profiles), ordered like the\nsite's /skills/ index: profession count desc, then label asc.\n\nExample: `curl https://jobriskindex.com/api/v1/skills`","operationId":"list_skills_api_v1_skills_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/skills/{slug}":{"get":{"tags":["Public API"],"summary":"Get Skill","description":"One skill plus the professions that require it as build\n(skills_to_acquire) and as enter (skills_to_enter, O*NET), with ids and\npublic URLs.\n\nExample: `curl https://jobriskindex.com/api/v1/skills/python`","operationId":"get_skill_api_v1_skills__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/salaries":{"get":{"tags":["Public API"],"summary":"Get Salaries","description":"Summary of salary-reference.json: p25/p50/p75 bands per aggregated\nsource for each occupation (only the published ones, with n ≥ threshold),\nthe bias notes of each source and the artifact date.\n\nExample: `curl https://jobriskindex.com/api/v1/salaries`","operationId":"get_salaries_api_v1_salaries_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/cities":{"get":{"tags":["Public API"],"summary":"Get Cities","description":"City demand (city-demand-reference.json): 10 cities with weekly series,\nrisk_demand and top professions — the same public artifact that feeds\n/cities/.\n\nExample: `curl https://jobriskindex.com/api/v1/cities`","operationId":"get_cities_api_v1_cities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/trends":{"get":{"tags":["Public API"],"summary":"Get Trends","description":"/trends/ movements (B1): professions rising/falling with their deltas\nbetween the second-to-last and the last complete week. Only real pipeline\nsignal (mock series are not published here nor on the site).\n\nExample: `curl https://jobriskindex.com/api/v1/trends`","operationId":"get_trends_api_v1_trends_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/search":{"get":{"tags":["Public API"],"summary":"Search","description":"Search professions by (id, title, aliases) — max 3 results (built so an\nLLM can resolve the exact profile with one request).\n\nExample: `curl \"https://jobriskindex.com/api/v1/search?q=data%20analyst\"`","operationId":"search_api_v1_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":120,"description":"Search term.","title":"Q"},"description":"Search term."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/meta":{"get":{"tags":["Public API"],"summary":"Get Meta","description":"Public dataset metadata: refresh date, counts and links to the\ndocumentation (OpenAPI + Swagger UI) and the rate-limit policy.\n\nExample: `curl https://jobriskindex.com/api/v1/meta`","operationId":"get_meta_api_v1_meta_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}