PolicyEngine API - Flask REST service powering policyengine.org and programmatic access
From essentialnpx claudepluginhub policyengine/policyengine-claude --plugin data-scienceThis skill uses the workspace's default tool permissions.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Optimizes cloud costs on AWS, Azure, GCP via rightsizing, tagging strategies, reserved instances, spot usage, and spending analysis. Use for expense reduction and governance.
The PolicyEngine API is a Flask-based REST service that provides tax and benefit calculations for the web app and programmatic users.
When you use policyengine.org, the API processes your calculations on our servers.
API base: https://api.policyengine.org
What it does:
The API is publicly accessible with rate limits:
Try it:
curl https://api.policyengine.org/us/policy/2
OpenAPI spec: https://api.policyengine.org/docs
Interactive docs: Swagger UI at API docs endpoint
Option 1: Python client (recommended)
# Use the policyengine package
# See policyengine-python-client-skill
Option 2: Direct API calls
import requests
# Calculate household impact
response = requests.post(
"https://api.policyengine.org/us/calculate",
json={
"household": household_situation,
"policy_id": None # or reform_id
}
)
result = response.json()
Household calculations:
POST /us/calculate
POST /uk/calculate
Policy management:
GET /us/policy/{policy_id}
POST /us/policy
Economy impacts:
GET /us/economy/{policy_id}/over/{baseline_policy_id}
Metadata:
GET /us/parameters
GET /us/variables
GET /us/parameter/{parameter_name}
GET /us/variable/{variable_name}
Rate limits:
Response times:
Optimization:
Location: PolicyEngine/policyengine-api
Clone:
git clone https://github.com/PolicyEngine/policyengine-api
cd policyengine-api
To see current structure:
tree policyengine_api/
# Key directories:
ls policyengine_api/
# - endpoints/ - HTTP endpoint handlers
# - routes/ - Route registration
# - services/ - Business logic
# - compute_api/ - Calculation services
# - economy_api/ - Economy impact calculations
# - utils/ - Helpers (caching, validation)
# - data/ - Static data
Reference endpoint (read this first):
cat policyengine_api/endpoints/economy.py
This demonstrates:
To find other endpoints:
ls policyengine_api/endpoints/
# - household.py
# - policy.py
# - economy.py
# - metadata.py
# - etc.
from flask import Blueprint, request, jsonify
from policyengine_api.utils import cache
blueprint = Blueprint("my_endpoint", __name__)
@blueprint.route("/us/calculate", methods=["POST"])
def calculate():
"""Standard pattern: validate, cache-check, compute, cache, return."""
try:
# 1. Get and validate input
data = request.json
if not data:
return jsonify({"error": "No data provided"}), 400
# 2. Generate cache key
cache_key = f"calc_{hash(str(data))}"
# 3. Check cache
cached = cache.get(cache_key)
if cached:
return jsonify(cached)
# 4. Compute
result = perform_calculation(data)
# 5. Cache result
cache.set(cache_key, result, expire=3600)
# 6. Return
return jsonify(result)
except Exception as e:
return jsonify({"error": str(e), "status": "error"}), 500
Current implementation details:
# See actual endpoint for current pattern
cat policyengine_api/endpoints/household.py
To see current caching implementation:
# Redis configuration
cat policyengine_api/utils/cache.py
# Find cache usage
grep -r "cache\." policyengine_api/endpoints/
Pattern:
For long-running calculations (population impacts):
To see current implementation:
# RQ (Redis Queue) usage
grep -r "@job" policyengine_api/
# Job patterns
cat policyengine_api/economy_api/
Pattern:
How API loads country packages:
cat policyengine_api/country.py
Pattern:
Business logic separated from endpoints:
ls policyengine_api/services/
Pattern:
# endpoints/household.py
from policyengine_api.services import household_service
@app.route("/us/calculate", methods=["POST"])
def calculate():
result = household_service.calculate(data)
return jsonify(result)
# services/household_service.py
def calculate(data):
# Business logic here
simulation = create_simulation(data)
return simulation.calculate(...)
When to delegate to policyengine.py:
The API should return None for dataset selection in most cases, allowing policyengine.py to choose the appropriate default dataset. This creates better separation of concerns.
Pattern:
# In economy_service.py _setup_data() method:
# ❌ DON'T: Explicitly specify datasets the API shouldn't control
if region == "ny":
return "gs://policyengine-us-data/some_dataset.h5"
# ✅ DO: Return None to let policyengine.py choose the default
if region in US_STATES:
return None # policyengine.py handles state-specific datasets
# ✅ DO: Only specify datasets for special cases the API needs to control
if region == "nyc":
return "gs://policyengine-us-data/pooled_3_year_cps_2023.h5" # NYC exception
Why this matters:
When to see this pattern:
policyengine_api/services/economy_service.py_setup_data() methodTo see current test patterns:
ls tests/
cat tests/test_household.py
Run tests:
make test
# Specific test
pytest tests/test_economy.py -v
# With coverage
make test-coverage
Start locally:
make debug
Test endpoint:
curl http://localhost:5000/us/policy/2
To see deployment configuration:
# Google Cloud Platform
cat app.yaml # App Engine config
cat cloudbuild.yaml # Cloud Build config
# Environment variables
cat .env.example
Current deployment:
To see versioning strategy:
grep -r "version" policyengine_api/
Current approach:
User/App → API Gateway → Flask App → Country Package → Core Engine
↓
Redis Cache
↓
Background Job (if needed)
↓
PostgreSQL (storage)
policyengine-core
↓
policyengine-us, policyengine-uk, etc.
↓
policyengine-api (you are here)
↓
policyengine-app (consumes API)
To understand dependencies:
policyengine-core-skill for engine patternspolicyengine-us-skill for country model usagepolicyengine-app-skill for how app calls APIStudy reference implementation:
cat policyengine_api/endpoints/economy.py
Create new endpoint file:
# policyengine_api/endpoints/my_endpoint.py
# Follow the pattern from economy.py
Register route:
# See route registration
cat policyengine_api/routes/__init__.py
Add tests:
# Follow test pattern
cat tests/test_economy.py
See current caching:
cat policyengine_api/utils/cache.py
Common changes:
To see how versions are managed:
# Requirements
cat requirements.txt | grep policyengine-
# Update and deploy
# See deployment docs in README
Always validate:
See validation examples:
grep -r "validate" policyengine_api/endpoints/
Standard error response:
return jsonify({
"error": "Error message",
"details": additional_context,
"status": "error"
}), status_code
See error patterns:
grep -A 5 "jsonify.*error" policyengine_api/endpoints/
To see logging configuration:
cat policyengine_api/gcp_logging.py
Pattern:
Repository: https://github.com/PolicyEngine/policyengine-api Live API: https://api.policyengine.org Documentation: https://api.policyengine.org/docs Status: https://status.policyengine.org