$npx -y skills add PolicyEngine/policyengine-claude --skill policyengine-apiLoad when consuming or developing the PolicyEngine REST APIs — the v1 Flask API at api.policyengine.org (production today) or the v2 alpha microservices in policyengine-api-v2. Covers the v1 endpoint surface (household calc, economy-over-baseline polling), the v2 architecture (th
| 1 | # PolicyEngine APIs |
| 2 | |
| 3 | Two APIs coexist: **v1** (`PolicyEngine/policyengine-api`, Flask) is production **today**, and |
| 4 | **v2** (`PolicyEngine/policyengine-api-v2`, FastAPI microservices) is in **alpha**. |
| 5 | |
| 6 | **Pick the right client first.** If you are computing policy impacts **from Python**, use the |
| 7 | `policyengine` package (`pe.us.calculate_household`, `Simulation`, `economic_impact_analysis`) |
| 8 | — see the **policyengine** skill. It pins a certified model + data bundle and is reproducible. |
| 9 | Reach for REST only for **apps and external integrations** (JS frontends, third parties) that |
| 10 | need HTTP. |
| 11 | |
| 12 | ## v1 API — production (`https://api.policyengine.org`) |
| 13 | |
| 14 | Flask (`policyengine_api`, Python 3.10/3.11). Country id (`us`, `uk`, `ca`, …) is the first |
| 15 | path segment. Verified route surface (`policyengine_api/routes/`, `api.py`): |
| 16 | |
| 17 | | Route | Method | Purpose | |
| 18 | |---|---|---| |
| 19 | | `/{country}/metadata` | GET | variables, parameters, entities | |
| 20 | | `/{country}/calculate` | POST | stateless household calc (household JSON in, values out) | |
| 21 | | `/{country}/calculate-full` | POST | stateless full household calc | |
| 22 | | `/{country}/household` | POST | create a stored household | |
| 23 | | `/{country}/household/{id}` | GET/PUT | fetch/update a stored household | |
| 24 | | `/{country}/household/{id}/policy/{policyId}` | GET | household calc under a stored policy | |
| 25 | | `/{country}/policy` · `/{country}/policy/{id}` | POST · GET | store / fetch a reform policy | |
| 26 | | `/{country}/economy/{policyId}/over/{baselinePolicyId}` | GET | society-wide reform impact | |
| 27 | | `/{country}/simulation`, `/{country}/report` | POST/GET/PATCH | stored simulations / report output | |
| 28 | | `/specification` | GET | OpenAPI spec (also `/liveness-check`, `/readiness-check`) | |
| 29 | |
| 30 | **The economy endpoint is asynchronous — poll it.** The same GET is re-issued until the job |
| 31 | finishes; the response is a status envelope, not the result on the first call: |
| 32 | |
| 33 | ```json |
| 34 | { "status": "computing" | "ok" | "error", |
| 35 | "queue_position": 3, "average_time": 42.0, |
| 36 | "result": { /* deciles, poverty, budget… once status == "ok" */ }, |
| 37 | "policyengine_bundle": { "model_version": "…", "data_version": "…" } } |
| 38 | ``` |
| 39 | |
| 40 | Query params on the economy call: `region` (`us`, or a two-letter state code; `uk`, etc.), |
| 41 | `time_period` (four-digit year), optional `dataset`. The household `POST /{country}/calculate` |
| 42 | body nests values by year (`{"people": {"you": {"age": {"2026": 40}}}, "households": {...}}`); |
| 43 | read `/{country}/metadata` for the exact variable and entity names rather than guessing. |
| 44 | |
| 45 | ## v2 API — alpha (`PolicyEngine/policyengine-api-v2`) |
| 46 | |
| 47 | A monorepo of FastAPI microservices, **not yet the production default**. Prerequisites: |
| 48 | Docker + Compose, Python 3.13+, **uv**, gcloud, Terraform. `make up` runs all services on |
| 49 | ports 8081–8083; `make test-complete` runs unit + integration; `make deploy` builds images and |
| 50 | applies Terraform. |
| 51 | |
| 52 | Three services: |
| 53 | |
| 54 | | Service | Port | Role | |
| 55 | |---|---|---| |
| 56 | | `api-full` | 8081 | main API — household calculations, policies | |
| 57 | | `api-simulation` | 8082 | economic (society-wide) simulation engine | |
| 58 | | `api-tagger` | 8083 | Cloud Run revision / release management | |
| 59 | |
| 60 | Stack (verified from `libs/policyengine-fastapi/pyproject.toml`): **FastAPI** |
| 61 | (`fastapi[standard]`) + **uvicorn**, **SQLModel / SQLAlchemy** for the datastore (sqlite for |
| 62 | desktop/testing via the shared `policyengine-fastapi` lib), OpenTelemetry instrumentation. It |
| 63 | is deployed to **Cloud Run** via Terraform. Each service generates an **OpenAPI spec and a |
| 64 | Python client library**; merges to main publish the client packages to **PyPI**. Structure: |
| 65 | `projects/` (the services + `policyengine-apis-integ` integration tests), `libs/` (shared |
| 66 | `policyengine-fastapi`), `deployment/` (docker-compose + terraform). |
| 67 | |
| 68 | Note: this repo uses SQLModel/SQLAlchemy, **not Supabase** — an older skill claimed Supabase, |
| 69 | but there is no Supabase reference anywhere in the repo. |
| 70 | |
| 71 | ## Integration status |
| 72 | |
| 73 | app-v2 already carries a **v2 alpha adapter** in `app/src/api/v2/` |
| 74 | (`API_V2_BASE_URL = process.env.NEXT_PUBLIC_API_V2_URL || 'https://v2.api.policyengine.org'`), |
| 75 | with endpoints per **policyengine-api-v2-alpha PR #77**. v2 calculations are **async job + |
| 76 | poll**, and it adds CRUD for households/policies/simulations. **Variation/axe |