Docs · Concepts

Request fields

Who this is for: Integrators building JSON bodies for POST /v1/deductions, batch pay runs, or year projection.

When you finish: You know which T4127 (Payroll Deductions Formulas) inputs are required, their defaults, and when to send each optional field.

A claim code is the TD1 box value that maps to federal and provincial personal amounts. Proration applies when Option 1 splits mid-year provincial rates (see effective-dates.md).

Money is always a quoted decimal string in dollars and cents (for example "1000.00"; "1000" and "1000.5" are read the same way as "1000.00" and "1000.50"). JSON numbers are rejected (HTTP 400 invalid_request naming the field). An amount with more than 2 decimal places (for example "1000.505") is refused with HTTP 400 invalid_request naming the field. Every money field is zero or more: a negative amount (for example "-50.00") is refused with HTTP 400 invalid_request whose message names the field, on POST /v1/deductions, on each item of a batch and on the year projection (-0.00 reads as zero). An amount may have at most 15 digits before the decimal point; a larger one is refused with HTTP 400 invalid_request naming the field. A year projection (POST /v1/deductions/year) also keeps running totals, so there gross_pay, pensionable_earnings, insurable_earnings, taxable_benefits and additional_tax_requested times the number of pay periods must stay within 15 digits too (HTTP 400 otherwise). The year projection takes only some of the fields below; see year-projection.md.

Six fields most callers need

Field Purpose
as_of Effective date (calendar date) that selects which enacted rule set applies.
province Two-letter jurisdiction code (ON, BC, AB, …).
pay_period Pay periods per year: one of 1, 2, 4, 10, 12, 13, 22, 24, 26, 27, 52, 53, 240 (daily) or 2000 (hourly).
gross_pay Taxable gross for this cheque.
federal_claim_code Federal TD1 claim code: 0 to 10 (a whole number, or its digits as a string) or E (or e).
provincial_claim_code Provincial TD1 claim code, the same values.

Claim codes and claim amounts

Send both claim codes, or the total claim amounts from the TD1 forms as federal_tc / provincial_tcp instead. A code and an amount for the same side in one request are refused (HTTP 400 invalid_request, ambiguous claim), so exactly one row below sets TC (federal) and TCP (provincial):

Sent TC or TCP used
federal_tc / provincial_tcp That amount
Code 0 $0.00 (no claim amount)
Code E $0.00, and that side's income tax is $0.00 (exempt; the Ontario Health Premium is still withheld)
Code 1, or no code The basic personal amount from its T4127 formula; the federal, Manitoba and Yukon amounts fall as net income rises
Codes 2 to 10 The TC or TCP the CRA prints for that code in the claim-code table (T4127 Chapter 8, Tables 8.9 to 8.21) of the edition as_of selects: the middle of the code's band of claim amounts

Codes 2 to 10 use the printed amount at every income; the income phase-out applies to code 1 and to no code. The CRA prints the July 2026 Newfoundland and Labrador table for Option 1 only (its basic amount, $15,000.00, is prorated; Option 2 uses $13,094.00), so from 2026-07-01 an NL provincial_claim_code from 2 to 10 with calculation_option option2 is refused with HTTP 400 invalid_request naming the field: send provincial_tcp instead. The response's breakdown.TC and breakdown.TCP show the amounts used. The tables are the CRA's CSV files archived in data/sources/ with their SHA-256 and pinned in the engine by SHA-512; the 2027 preview reuses the July 2026 tables.

Identity and dates

Field Type Default Required T4127 factor When needed
as_of date Worker UTC date if omitted Recommended always Selects tables for R, K, V, YMPE (Year's Maximum Pensionable Earnings), BPAF (Basic Personal Amount Factor) Every production call; omit only when you accept the server clock
province string none Yes Table 8.1 jurisdiction Always
pay_period integer none Yes P, PR Always; must be a legal T4127 period count
prior_province string none No Not read Refused (HTTP 400 invalid_request naming the field) when sent with a value: a change of province during the year is not calculated; send the province of employment on the pay date as province
date_of_birth date none No Not read Refused (HTTP 400 invalid_request naming the field) when sent with a value: no age-based CPP rule is applied from it; use cpp_exempt and cpp_months
calculation_option string option1 No Option 1 vs Option 2 annualization BC, NL, PE mid-year proration paths; see effective-dates.md
cpp_months integer, 0 to 12 12 No CPP contribution months Short-year employment
k2_method string pdoc_observed No K2 / K2P base PDOC reconciliation vs literal T4127
rounding_compat string t4127 No C (period CPP) pdoc reproduces PDOC's binary64 CPP line to the cent (ADR-007)

Income

Field Type Default Required T4127 factor When needed
gross_pay money none Yes Feeds IE, annual A Always
pensionable_earnings money gross_pay No CPP pensionable Differs from gross (benefits, caps)
insurable_earnings money gross_pay No EI insurable Differs from gross
taxable_benefits money 0.00 No Taxable allowances Non-cash taxable items in the period
retroactive_pay money none No Retroactive lump T4127 retro pay instructions

Claims and personal amounts

Field Type Default Required T4127 factor When needed
federal_claim_code int/string none One of code or TC TC, K1 Default withholding setup
provincial_claim_code int/string none One of code or TCP TCP, K1P Default withholding setup
federal_tc money none Mutually exclusive with code TC Custom federal total claim amount
provincial_tcp money none Mutually exclusive with code TCP Custom provincial total claim amount
dependants_under_19 integer, 0 to 99 none No Provincial credits MB and similar
dependants_disabled integer, 0 to 99 none No Provincial credits Where TD1X applies

Deductions from pay

Field Type Default Required T4127 factor When needed
rpp money none No Registered pension Period RRSP/RPP
union_dues money none No Union dues credit Period dues
alimony money none No Support payments Ordered deductions
child_care_expenses money none No Child care Provincial rules
prescribed_zone_deduction money none No Northern deduction Zone allowances
lcf_purchase money none No LCF Labour-sponsored funds
lcp_purchase money none No LCP Provincial labour credit
additional_tax_requested money none No L extra tax TD1 “additional tax” box
cpp_exempt boolean false No CPP exemption Valid exemption on file
cpp_election_after_65 boolean none No Not read Refused (HTTP 400 invalid_request naming the field) when sent with a value, false included: the CPP election to stop contributing is not applied from it; use cpp_exempt and cpp_months

Year-to-date (YTD)

Field Type Default Required T4127 factor When needed
ytd_pensionable_earnings money none No CPP YTD PE Mid-year hire or CPP cap
ytd_insurable_earnings money none No EI YTD EI cap tracking
ytd_cpp money none No D CPP paid YTD
ytd_cpp2 money none No D2, CPP2 (second additional CPP) YAMPE (Year's Additional Maximum Pensionable Earnings) band
ytd_ei money none No EI premiums YTD EI cap
ytd_federal_tax money none No Federal tax paid Bonus methods
ytd_provincial_tax money none No Provincial tax paid Bonus methods
ytd_income money none No Cumulative income Commission averaging
ytd_rpp money none No RPP YTD Annualized RPP
ytd_union_dues money none No Dues YTD Credits
f5a_ytd money none No F5A YTD CPP additional
f5b_ytd money none No F5B YTD CPP additional
pay_periods_elapsed integer, 0 to pay_period none No Period index Mid-year start
ytd_qpp money none No Quebec only Refused (HTTP 400 invalid_request naming the field) when sent with a value: Quebec is not calculated (a QC request is HTTP 422 jurisdiction_not_supported)
ytd_qpp2 money none No Quebec only Refused the same way
ytd_qpip money none No Quebec only Refused the same way

Bonus and lump sums

Field Type Default Required T4127 factor When needed
bonus money none No Bonus withholding T4127 bonus method
bonus_method string regular No Method selector Alternate bonus treatment
ytd_bonus money none No YTD bonus Cumulative bonus
bonus_rrsp money none No Bonus RRSP Special RRSP bonus
ytd_bonus_rrsp money none No YTD bonus RRSP Tracking
most_recent_i money none No Recent insurable Bonus averaging

Option 2 and commission

Field Type Default Required T4127 factor When needed
calculation_option string option1 No Option 1 vs 2 Set option2 when your software uses T4127 Option 2
commission_income money none No Not read Refused (HTTP 400 invalid_request naming the field) when sent with a value: the T4127 commission method (Form TD1X) is not calculated; send commission paid with the cheque in gross_pay or bonus
commission_expenses money none No Not read Refused the same way
estimated_annual_expenses money none No Expense estimate Annual expense election

Unknown property names yield unknown_field (HTTP 400). The API strips no extra keys silently, on any route. In a batch, every field goes on each item: the envelope takes only requests, and a field next to it (for example federal_claim_code or as_of) is refused. A documented field the engine does not read (prior_province, date_of_birth, cpp_election_after_65, commission_income, commission_expenses, ytd_qpp, ytd_qpp2 and ytd_qpip) is refused by name whenever it is sent with a value; null is read as not sent. A value of the wrong type or outside the values its field takes (for example pay_period 3, a claim code 11, cpp_months 256), and a required field left out, are HTTP 400 invalid_request naming the field.

See api-reference.md for routes and errors.md for rejection behavior.

Last reviewed: 2026-10-24
Engine: 0.1.0

Source: docs/request-fields.md in the Takehome repository, rendered as written.