1414
1515
1616class HouseholdCalculateRequest (BaseModel ):
17- """Request body for household calculation."""
17+ """Request body for household calculation.
18+
19+ IMPORTANT: Use flat values for variables, NOT time-period dictionaries.
20+ The year is specified separately via the `year` parameter.
21+
22+ CORRECT: {"employment_income": 70000, "age": 40}
23+ WRONG: {"employment_income": {"2024": 70000}, "age": {"2024": 40}}
24+
25+ Example US request:
26+ {
27+ "tax_benefit_model_name": "policyengine_us",
28+ "people": [{"employment_income": 70000, "age": 40}],
29+ "tax_unit": {"state_code": "CA"},
30+ "household": {"state_fips": 6},
31+ "year": 2024
32+ }
33+
34+ Example UK request:
35+ {
36+ "tax_benefit_model_name": "policyengine_uk",
37+ "people": [{"employment_income": 50000, "age": 30}],
38+ "household": {},
39+ "year": 2026
40+ }
41+ """
1842
19- tax_benefit_model_name : Literal ["policyengine_uk" , "policyengine_us" ]
20- people : list [dict [str , Any ]]
21- benunit : dict [str , Any ] = Field (default_factory = dict )
22- marital_unit : dict [str , Any ] = Field (default_factory = dict )
23- family : dict [str , Any ] = Field (default_factory = dict )
24- spm_unit : dict [str , Any ] = Field (default_factory = dict )
25- tax_unit : dict [str , Any ] = Field (default_factory = dict )
26- household : dict [str , Any ] = Field (default_factory = dict )
27- year : int | None = None
28- policy_id : UUID | None = None
29- dynamic_id : UUID | None = None
43+ tax_benefit_model_name : Literal ["policyengine_uk" , "policyengine_us" ] = Field (
44+ description = "Which country model to use"
45+ )
46+ people : list [dict [str , Any ]] = Field (
47+ description = "List of people with flat variable values (e.g. [{'age': 30, 'employment_income': 50000}]). Do NOT use time-period format."
48+ )
49+ benunit : dict [str , Any ] = Field (
50+ default_factory = dict , description = "UK benefit unit variables (flat values)"
51+ )
52+ marital_unit : dict [str , Any ] = Field (
53+ default_factory = dict , description = "US marital unit variables (flat values)"
54+ )
55+ family : dict [str , Any ] = Field (
56+ default_factory = dict , description = "US family variables (flat values)"
57+ )
58+ spm_unit : dict [str , Any ] = Field (
59+ default_factory = dict , description = "US SPM unit variables (flat values)"
60+ )
61+ tax_unit : dict [str , Any ] = Field (
62+ default_factory = dict ,
63+ description = "US tax unit variables (flat values, e.g. {'state_code': 'CA'})" ,
64+ )
65+ household : dict [str , Any ] = Field (
66+ default_factory = dict ,
67+ description = "Household variables (flat values, e.g. {'state_fips': 6} for US)" ,
68+ )
69+ year : int | None = Field (
70+ default = None ,
71+ description = "Simulation year (default: 2024 for US, 2026 for UK). Specify this instead of embedding years in variable values." ,
72+ )
73+ policy_id : UUID | None = Field (
74+ default = None , description = "Optional policy reform ID"
75+ )
76+ dynamic_id : UUID | None = Field (
77+ default = None , description = "Optional behavioural response ID"
78+ )
3079
3180
3281class HouseholdCalculateResponse (BaseModel ):
@@ -42,19 +91,54 @@ class HouseholdCalculateResponse(BaseModel):
4291
4392
4493class HouseholdImpactRequest (BaseModel ):
45- """Request body for household impact comparison."""
94+ """Request body for household impact comparison.
95+
96+ Same format as HouseholdCalculateRequest - use flat values, NOT time-period dictionaries.
97+
98+ Example:
99+ {
100+ "tax_benefit_model_name": "policyengine_us",
101+ "people": [{"employment_income": 70000, "age": 40}],
102+ "tax_unit": {"state_code": "CA"},
103+ "household": {"state_fips": 6},
104+ "year": 2024,
105+ "policy_id": "uuid-of-reform-policy"
106+ }
107+ """
46108
47- tax_benefit_model_name : Literal ["policyengine_uk" , "policyengine_us" ]
48- people : list [dict [str , Any ]]
49- benunit : dict [str , Any ] = Field (default_factory = dict )
50- marital_unit : dict [str , Any ] = Field (default_factory = dict )
51- family : dict [str , Any ] = Field (default_factory = dict )
52- spm_unit : dict [str , Any ] = Field (default_factory = dict )
53- tax_unit : dict [str , Any ] = Field (default_factory = dict )
54- household : dict [str , Any ] = Field (default_factory = dict )
55- year : int | None = None
56- policy_id : UUID | None = None # Reform policy (baseline uses no policy)
57- dynamic_id : UUID | None = None
109+ tax_benefit_model_name : Literal ["policyengine_uk" , "policyengine_us" ] = Field (
110+ description = "Which country model to use"
111+ )
112+ people : list [dict [str , Any ]] = Field (
113+ description = "List of people with flat variable values. Do NOT use time-period format."
114+ )
115+ benunit : dict [str , Any ] = Field (
116+ default_factory = dict , description = "UK benefit unit variables (flat values)"
117+ )
118+ marital_unit : dict [str , Any ] = Field (
119+ default_factory = dict , description = "US marital unit variables (flat values)"
120+ )
121+ family : dict [str , Any ] = Field (
122+ default_factory = dict , description = "US family variables (flat values)"
123+ )
124+ spm_unit : dict [str , Any ] = Field (
125+ default_factory = dict , description = "US SPM unit variables (flat values)"
126+ )
127+ tax_unit : dict [str , Any ] = Field (
128+ default_factory = dict , description = "US tax unit variables (flat values)"
129+ )
130+ household : dict [str , Any ] = Field (
131+ default_factory = dict , description = "Household variables (flat values)"
132+ )
133+ year : int | None = Field (
134+ default = None , description = "Simulation year (default: 2024 for US, 2026 for UK)"
135+ )
136+ policy_id : UUID | None = Field (
137+ default = None , description = "Reform policy ID to compare against baseline"
138+ )
139+ dynamic_id : UUID | None = Field (
140+ default = None , description = "Optional behavioural response ID"
141+ )
58142
59143
60144class HouseholdImpactResponse (BaseModel ):
@@ -148,7 +232,14 @@ def calculate_household(
148232 request : HouseholdCalculateRequest ,
149233 session : Session = Depends (get_session ),
150234) -> HouseholdCalculateResponse :
151- """Calculate tax and benefit impacts for a household."""
235+ """Calculate tax and benefit impacts for a household.
236+
237+ Use flat values for all variables - do NOT use time-period format like {"2024": value}.
238+ The simulation year is specified via the `year` parameter.
239+
240+ US example: people=[{"employment_income": 70000, "age": 40}], tax_unit={"state_code": "CA"}, year=2024
241+ UK example: people=[{"employment_income": 50000, "age": 30}], year=2026
242+ """
152243 if request .tax_benefit_model_name == "policyengine_uk" :
153244 from policyengine .tax_benefit_models .uk import uk_latest
154245
@@ -275,6 +366,8 @@ def calculate_household_impact_comparison(
275366
276367 Compares the household under baseline (current law) vs reform (policy_id).
277368 Returns both calculations plus computed differences.
369+
370+ Use flat values for all variables - do NOT use time-period format like {"2024": value}.
278371 """
279372 # Build baseline request (no policy)
280373 baseline_request = HouseholdCalculateRequest (
0 commit comments