Tax API Reference
Income tax, National Insurance (including category letters and the directors' annual method), tax years, take-home pay, tax comparison, employer cost, VAT, Capital Gains Tax, dividend tax, student loans, pension allowances, and Corporation Tax.
Base URL: https://api.govdata.dev/v1
Tax Years
/v1/tax/years
No parameters required.
Waiting for request...
List all available tax years.
curl -H "Authorization: Bearer YOUR_API_KEY" \ https://api.govdata.dev/v1/tax/years
uri = URI("https://api.govdata.dev/v1/tax/years") req = Net::HTTP::Get.new(uri) req["Authorization"] = "Bearer YOUR_API_KEY" res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
response = requests.get( "https://api.govdata.dev/v1/tax/years", headers={"Authorization": "Bearer YOUR_API_KEY"} )
const response = await fetch("https://api.govdata.dev/v1/tax/years", { headers: { "Authorization": "Bearer YOUR_API_KEY" } });
Response
{ "data": [ { "identifier": "2026-27", "start_date": "2026-04-06", "end_date": "2027-04-05", "active": true, "key_dates": { "self_assessment_deadline": "2028-01-31", "payment_on_account_first": "2027-01-31", "payment_on_account_second": "2027-07-31", "p60_deadline": "2027-05-31", "p11d_deadline": "2027-07-06" } } ], "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0" }, "pagination": { "total": 37, "page": 1, "per_page": 25, "total_pages": 1 } }
/v1/tax/years/current
No parameters required.
Waiting for request...
Returns the current active tax year.
/v1/tax/years/:identifier
Waiting for request...
Returns a specific tax year by identifier.
| Parameter | Type | Description |
|---|---|---|
identifier |
string | Tax year in YYYY-YY format (e.g., 2025-26) |
Income Tax
/v1/tax/income/bands
No parameters required.
Waiting for request...
Returns income tax bands for the current tax year. Append /:tax_year for a specific year.
curl -H "Authorization: Bearer YOUR_API_KEY" \ https://api.govdata.dev/v1/tax/income/bands
uri = URI("https://api.govdata.dev/v1/tax/income/bands") req = Net::HTTP::Get.new(uri) req["Authorization"] = "Bearer YOUR_API_KEY" res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
response = requests.get( "https://api.govdata.dev/v1/tax/income/bands", headers={"Authorization": "Bearer YOUR_API_KEY"} )
const response = await fetch("https://api.govdata.dev/v1/tax/income/bands", { headers: { "Authorization": "Bearer YOUR_API_KEY" } });
Response
{ "data": { "tax_year": "2025-26", "personal_allowance": 12570, "personal_allowance_taper_threshold": 100000, "regions": { "england_wales_ni": { "bands": [ { "name": "basic_rate", "label": "Basic Rate", "rate": 0.20, "from": 12570, "to": 50270 }, { "name": "higher_rate", "label": "Higher Rate", "rate": 0.40, "from": 50270, "to": 125140 }, { "name": "additional_rate", "label": "Additional Rate", "rate": 0.45, "from": 125140, "to": null } ] }, "scotland": { "bands": [ { "name": "starter_rate", "rate": 0.19, "from": 12570, "to": 15325 }, { "name": "basic_rate", "rate": 0.20, "from": 15325, "to": 43662 }, { "name": "intermediate_rate", "rate": 0.21, "from": 43662, "to": 50270 }, { "name": "higher_rate", "rate": 0.41, "from": 50270, "to": 125140 }, { "name": "top_rate", "rate": 0.46, "from": 125140, "to": null } ] } } }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/income-tax-rates" } }
/v1/tax/income/calculate
Waiting for request...
Calculate income tax for a given gross income.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
gross_income |
integer | Yes | Annual gross income in pounds (e.g., 55000) |
region |
string | No | Default: england_wales_ni. Also: scotland |
tax_year |
string | No | Default: current year. Format: YYYY-YY |
marriage_allowance_recipient |
boolean | No | This person receives a transferred Marriage Allowance. Reduces tax by 20% of the transferred amount (£252 in 2025-26 and 2026-27). Only basic rate taxpayers are eligible (starter/basic/intermediate in Scotland) — a higher-rate income returns a 422 marriage_allowance_ineligible error. |
marriage_allowance_transferor |
boolean | No | This person transfers Marriage Allowance to their partner, reducing their own personal_allowance by the transferable amount. |
blind_persons_allowance |
boolean | No | Adds Blind Person's Allowance to the personal_allowance (£3,250 in 2026-27, £3,130 in 2025-26). Additive, not tapered — applies at any income and composes with Marriage Allowance. UK-wide (same for rUK and Scotland). Spouse transfer of unused allowance is not supported. |
See gov.uk/marriage-allowance and gov.uk/blind-persons-allowance for eligibility rules.
curl -X POST https://api.govdata.dev/v1/tax/income/calculate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"gross_income": 55000, "region": "england_wales_ni"}'
uri = URI("https://api.govdata.dev/v1/tax/income/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = { gross_income: 55000, region: "england_wales_ni" }.to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/income/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={"gross_income": 55000, "region": "england_wales_ni"} )
const response = await fetch("https://api.govdata.dev/v1/tax/income/calculate", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ gross_income: 55000, region: "england_wales_ni" }) });
Response
{ "data": { "gross_income": 55000, "personal_allowance": 12570, "taxable_income": 42430, "tax_year": "2025-26", "region": "england_wales_ni", "breakdown": [ { "band": "basic_rate", "rate": 0.20, "taxable_amount": 37700, "tax": 7540.00 }, { "band": "higher_rate", "rate": 0.40, "taxable_amount": 4730, "tax": 1892.00 } ], "total_income_tax": 9432.00, "effective_rate": 0.1715 }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC" } }
With Marriage Allowance
Passing marriage_allowance_recipient: true for a £30,000 basic-rate income adds a marriage_allowance object and reduces total_income_tax by the tax reduction:
{ "data": { "gross_income": 30000, "personal_allowance": 12570, "taxable_income": 17430, "total_income_tax": 3234.00, "effective_rate": 0.1078, "marriage_allowance": { "eligible": true, "transferred_amount": 1260, "tax_reduction": 252.00 } } }
If the recipient's income falls into a higher tax band, the request returns a 422 with code marriage_allowance_ineligible. Use marriage_allowance_transferor: true instead to reduce the transferor's own personal_allowance by the transferable amount (£1,260 in 2025-26 and 2026-27).
With Blind Person's Allowance
Passing blind_persons_allowance: true adds the allowance (£3,250 in 2026-27) directly to personal_allowance before tax is calculated — for a £30,000 income, Personal Allowance rises to £15,820 and taxable income falls to £14,180:
{ "data": { "gross_income": 30000, "personal_allowance": 15820, "taxable_income": 14180, "total_income_tax": 2836.00, "effective_rate": 0.0945 } }
Composes with marriage_allowance_recipient/marriage_allowance_transferor — Blind Person's Allowance is added after any Marriage Allowance transfer, and is never reduced by it. Spouse transfer of unused Blind Person's Allowance is not supported.
National Insurance
/v1/tax/national-insurance/thresholds
No parameters required.
Waiting for request...
Returns National Insurance thresholds for the current tax year. Append /:tax_year for a specific year.
Response
{ "data": { "tax_year": "2025-26", "employee": { "primary_threshold": { "annual": 12570, "weekly": 241.73 }, "upper_earnings_limit": { "annual": 50270, "weekly": 967.12 } }, "employer": { "secondary_threshold": { "annual": 5000 } }, "self_employed": { "class_2_small_profits_threshold": { "annual": 6725 }, "class_4_lower_profit_limit": { "annual": 12570 }, "class_4_upper_profit_limit": { "annual": 50270 } } }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/national-insurance-rates-letters" } }
/v1/tax/national-insurance/categories
Waiting for request...
Returns every current UK National Insurance category letter (A, B, C, H, J, M, V, Z, plus the Freeport and Investment Zone letters) with a description of who it applies to and the employee/employer contribution rates for that letter.
Response
{ "data": { "tax_year": "2025-26", "categories": [ { "letter": "A", "description": "All employees apart from those in groups B, C, H, J, M, V and Z in this table", "group": "standard", "employee": { "rate_main": 0.08, "rate_upper": 0.02 }, "employer": { "rate": 0.15, "reduced_rate": false } }, { "letter": "C", "description": "Employees over the State Pension age", "group": "state_pension_age", "employee": { "rate_main": null, "rate_upper": null }, "employer": { "rate": 0.15, "reduced_rate": false } }, { "letter": "H", "description": "Apprentices under 25", "group": "apprentice_under_25", "employee": { "rate_main": 0.08, "rate_upper": 0.02 }, "employer": { "rate": 0.15, "reduced_rate": true } } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/national-insurance-rates-letters" } }
"rate_main" is the rate charged between the primary threshold and upper earnings limit; "rate_upper" is the rate above the upper earnings limit. Both are null for categories with no employee contribution (state pension age and the "X" no-NI marker). "reduced_rate" marks categories where the employer pays 0% up to that category's own upper secondary threshold.
/v1/tax/national-insurance/calculate
Waiting for request...
Calculate National Insurance contributions for employed or self-employed income.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
annual_salary |
integer | Yes* | Annual salary in pounds (for employed type) |
annual_profit |
integer | Yes* | Annual profit in pounds (for self_employed type) |
type |
string | No | Default: employed. Also: self_employed |
tax_year |
string | No | Default: current year. Format: YYYY-YY |
director |
boolean | No | Use HMRC's directors' annual (cumulative) NI method — applies annual PT/UEL/ST thresholds. Only valid with type: employed; otherwise returns 422 director_not_applicable. The response's method field reports which method was used (standard or directors_annual). |
* Use annual_salary for employed, annual_profit for self-employed. See gov.uk/employee-directors for the directors' annual method.
curl -X POST https://api.govdata.dev/v1/tax/national-insurance/calculate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"annual_salary": 55000, "type": "employed"}'
uri = URI("https://api.govdata.dev/v1/tax/national-insurance/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = { annual_salary: 55000, type: "employed" }.to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/national-insurance/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={"annual_salary": 55000, "type": "employed"} )
const response = await fetch("https://api.govdata.dev/v1/tax/national-insurance/calculate", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ annual_salary: 55000, type: "employed" }) });
Directors' annual method
Passing director: true assesses NI using HMRC's default annual (cumulative) method for company directors — the same annual PT/UEL/ST thresholds, so the figures for a given annual_salary match the standard calculation. The response's method field confirms which method was applied:
{ "data": { "annual_salary": 55000, "tax_year": "2026-27", "type": "employed", "method": "directors_annual", "employee": { "contributions": 3110.60, "breakdown": [ ... ] }, "employer": { "contributions": 7500.00, "breakdown": [ ... ] } } }
Only HMRC's annual method is implemented. The optional "alternative" (period-by-period) method reconciles to the same annual total at year end and is out of scope. director: true with type: self_employed returns a 422 with code director_not_applicable.
Take-Home Calculator
/v1/tax/take-home/calculate
Waiting for request...
Combined income tax and National Insurance calculation. Returns net pay breakdown with annual, monthly, and weekly figures.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
gross_income |
integer | Yes | Annual gross income in pounds |
region |
string | No | Default: england_wales_ni |
tax_year |
string | No | Default: current year |
marriage_allowance_recipient |
boolean | No | Adds a deductions.income_tax.marriage_allowance object and reduces income tax by 20% of the transferred amount. Basic rate taxpayers only (starter/basic/intermediate in Scotland) — otherwise returns 422 marriage_allowance_ineligible. |
marriage_allowance_transferor |
boolean | No | Reduces this person's own personal_allowance by the transferred amount. |
blind_persons_allowance |
boolean | No | Adds Blind Person's Allowance to deductions.income_tax.personal_allowance (£3,250 in 2026-27, £3,130 in 2025-26). Additive, not tapered, composes with Marriage Allowance. |
curl -X POST https://api.govdata.dev/v1/tax/take-home/calculate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"gross_income": 55000, "region": "england_wales_ni"}'
uri = URI("https://api.govdata.dev/v1/tax/take-home/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = { gross_income: 55000, region: "england_wales_ni" }.to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/take-home/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={"gross_income": 55000, "region": "england_wales_ni"} )
const response = await fetch("https://api.govdata.dev/v1/tax/take-home/calculate", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ gross_income: 55000, region: "england_wales_ni" }) });
Response
{ "data": { "gross_income": 55000, "region": "england_wales_ni", "tax_year": "2025-26", "deductions": { "income_tax": { "amount": 9432.00, "personal_allowance": 12570, "effective_rate": 0.1715, "breakdown": [ { "band": "basic_rate", "rate": 0.20, "taxable_amount": 37700, "tax": 7540.00 }, { "band": "higher_rate", "rate": 0.40, "taxable_amount": 4730, "tax": 1892.00 } ] }, "national_insurance": { "employee": 3110.60, "breakdown": [ { "from": 12570, "to": 50270, "rate": 0.08, "amount": 3016.00 }, { "from": 50270, "to": 55000, "rate": 0.02, "amount": 94.60 } ] } }, "net_annual": 42457.40, "net_monthly": 3538.12, "net_weekly": 816.49, "total_deductions": 12542.60, "marginal_rate": 0.42, "employer_costs": { "employer_ni": 7500.00, "total_cost_to_employer": 62500.00 } }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC" } }
Tax Comparison
/v1/tax/compare
Waiting for request...
Compare take-home pay between two scenarios. Takes two sets of inputs and returns a side-by-side comparison with absolute and percentage differences.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
scenario_a |
object | Yes | First scenario (gross_income required, plus optional region, student_loan_plans, pension_contribution_percent, pension_type) |
scenario_b |
object | Yes | Second scenario (same fields as scenario_a) |
tax_year |
string | No | Shared tax year for both scenarios. Default: current year |
curl -X POST https://api.govdata.dev/v1/tax/compare \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"scenario_a":{"gross_income":50000,"region":"england_wales_ni"},"scenario_b":{"gross_income":60000,"region":"scotland"}}'
uri = URI("https://api.govdata.dev/v1/tax/compare") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = { scenario_a: { gross_income: 50000, region: "england_wales_ni" }, scenario_b: { gross_income: 60000, region: "scotland" } }.to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/compare", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "scenario_a": {"gross_income": 50000, "region": "england_wales_ni"}, "scenario_b": {"gross_income": 60000, "region": "scotland"} } )
const response = await fetch("https://api.govdata.dev/v1/tax/compare", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ scenario_a: { gross_income: 50000, region: "england_wales_ni" }, scenario_b: { gross_income: 60000, region: "scotland" } }) });
Response
{ "data": { "scenario_a": { "gross_income": 50000, "region": "england_wales_ni", "tax_year": "2025-26", "net_annual": 38957.40, "total_deductions": 11042.60, "marginal_rate": 0.42, "..." }, "scenario_b": { "gross_income": 60000, "region": "scotland", "tax_year": "2025-26", "net_annual": 45678.90, "total_deductions": 14321.10, "marginal_rate": 0.53, "..." }, "differences": { "gross_income": { "absolute": 10000, "percentage": 20.0 }, "net_annual": { "absolute": 6721.50, "percentage": 17.25 }, "total_deductions": { "absolute": 3278.50, "percentage": 29.69 }, "income_tax": { "absolute": 2432.00, "percentage": 32.36 }, "national_insurance": { "absolute": 94.60, "percentage": 3.15 }, "marginal_rate": { "absolute": 0.11, "percentage": 26.19 } } }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC" } }
VAT Return Calculation
Calculate a nine-box VAT return
Returns all nine UK VAT Return boxes plus transaction breakdowns, warnings, scheme totals, and rounding information for accountants, finance teams, and bookkeeping products. Validate a quarter before filing with HMRC or explain exactly which sales and purchases contributed to each box.
/v1/tax/vat/return/calculate
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
company |
object | Yes | — | VAT registration number, dated vat_schemes array, and partially_exempt boolean. |
period |
object | Yes | — | Inclusive start_date and end_date in YYYY-MM-DD format. |
transactions |
array | Yes | — | Transaction objects: id, date, type, net_amount, vat_amount, gross_amount, vat_rate, vat_rate_percentage, supply_type, and is_capital_asset; maximum 10,000. |
breakdown_detail |
string | No | summary | summary, detailed, or none; controls the returned breakdown, not the box calculation. |
curl -X POST "https://api.govdata.dev/v1/tax/vat/return/calculate" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"company":{"vat_registration_number":"123456789","vat_schemes":[{"scheme":"standard","effective_from":"2025-01-01","effective_to":null}],"partially_exempt":false},"period":{"start_date":"2025-01-01","end_date":"2025-03-31"},"transactions":[{"id":"S001","date":"2025-01-15","type":"sale","net_amount":10000,"vat_amount":2000,"gross_amount":12000,"vat_rate":"standard","vat_rate_percentage":20,"supply_type":"domestic","is_capital_asset":false},{"id":"P001","date":"2025-02-01","type":"purchase","net_amount":3000,"vat_amount":600,"gross_amount":3600,"vat_rate":"standard","vat_rate_percentage":20,"supply_type":"domestic","is_capital_asset":false}]}'
uri = URI("https://api.govdata.dev/v1/tax/vat/return/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = JSON.parse('{"company":{"vat_registration_number":"123456789","vat_schemes":[{"scheme":"standard","effective_from":"2025-01-01","effective_to":null}],"partially_exempt":false},"period":{"start_date":"2025-01-01","end_date":"2025-03-31"},"transactions":[{"id":"S001","date":"2025-01-15","type":"sale","net_amount":10000,"vat_amount":2000,"gross_amount":12000,"vat_rate":"standard","vat_rate_percentage":20,"supply_type":"domestic","is_capital_asset":false},{"id":"P001","date":"2025-02-01","type":"purchase","net_amount":3000,"vat_amount":600,"gross_amount":3600,"vat_rate":"standard","vat_rate_percentage":20,"supply_type":"domestic","is_capital_asset":false}]}').to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/vat/return/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json=json.loads('{"company":{"vat_registration_number":"123456789","vat_schemes":[{"scheme":"standard","effective_from":"2025-01-01","effective_to":null}],"partially_exempt":false},"period":{"start_date":"2025-01-01","end_date":"2025-03-31"},"transactions":[{"id":"S001","date":"2025-01-15","type":"sale","net_amount":10000,"vat_amount":2000,"gross_amount":12000,"vat_rate":"standard","vat_rate_percentage":20,"supply_type":"domestic","is_capital_asset":false},{"id":"P001","date":"2025-02-01","type":"purchase","net_amount":3000,"vat_amount":600,"gross_amount":3600,"vat_rate":"standard","vat_rate_percentage":20,"supply_type":"domestic","is_capital_asset":false}]}') )
const response = await fetch("https://api.govdata.dev/v1/tax/vat/return/calculate", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify(JSON.parse('{"company":{"vat_registration_number":"123456789","vat_schemes":[{"scheme":"standard","effective_from":"2025-01-01","effective_to":null}],"partially_exempt":false},"period":{"start_date":"2025-01-01","end_date":"2025-03-31"},"transactions":[{"id":"S001","date":"2025-01-15","type":"sale","net_amount":10000,"vat_amount":2000,"gross_amount":12000,"vat_rate":"standard","vat_rate_percentage":20,"supply_type":"domestic","is_capital_asset":false},{"id":"P001","date":"2025-02-01","type":"purchase","net_amount":3000,"vat_amount":600,"gross_amount":3600,"vat_rate":"standard","vat_rate_percentage":20,"supply_type":"domestic","is_capital_asset":false}]}')) });
Response
{ "data": { "return_period": { "start_date": "2025-01-01", "end_date": "2025-03-31" }, "boxes": { "box_1": { "value": 2000.0, "exact_value": 2000.0 }, "box_2": { "value": 0.0, "exact_value": 0.0 }, "box_4": { "value": 600.0, "exact_value": 600.0 }, "box_3": { "value": 2000.0, "exact_value": 2000.0 }, "box_5": { "value": 1400.0, "exact_value": 1400.0 }, "box_6": { "value": 10000.0, "exact_value": 10000.0 }, "box_7": { "value": 3000.0, "exact_value": 3000.0 }, "box_8": { "value": 0.0, "exact_value": 0.0 }, "box_9": { "value": 0.0, "exact_value": 0.0 } }, "warnings": [], "scheme_summary": [ { "scheme": "standard", "effective_from": "2025-01-01", "effective_to": "2025-03-31", "transaction_count": 2 } ], "rounding_summary": { "box_1_rounding": 0.0, "box_2_rounding": 0.0, "box_3_rounding": 0.0, "box_4_rounding": 0.0, "box_5_rounding": 0.0, "box_6_rounding": 0.0, "box_7_rounding": 0.0, "box_8_rounding": 0.0, "box_9_rounding": 0.0 }, "breakdown": { "box_1": { "description": "VAT due on sales and other outputs", "total": 2000.0, "exact_total": 2000.0, "components": [ { "label": "Standard-rated domestic sales", "total": 2000.0, "exact_total": 2000.0, "transaction_count": 1, "transaction_ids": [ "S001" ] } ] }, "box_2": { "description": "VAT due on acquisitions from other EC member states", "total": 0.0, "exact_total": 0.0, "components": [] }, "box_3": { "description": "Total VAT due (Box 1 + Box 2)", "total": 2000.0, "exact_total": 2000.0, "derivation": "box_1 + box_2" }, "box_4": { "description": "VAT reclaimed on purchases and other inputs", "total": 600.0, "exact_total": 600.0, "components": [ { "label": "Input VAT on standard-rated domestic purchases", "total": 600.0, "exact_total": 600.0, "transaction_count": 1, "transaction_ids": [ "P001" ] } ] }, "box_5": { "description": "Net VAT due or reclaimable (Box 3 - Box 4)", "total": 1400.0, "exact_total": 1400.0, "derivation": "box_3 - box_4" }, "box_6": { "description": "Total value of sales and all other outputs excluding VAT", "total": 10000.0, "exact_total": 10000.0, "components": [ { "label": "Standard-rated domestic sales", "total": 10000.0, "exact_total": 10000.0, "transaction_count": 1, "transaction_ids": [ "S001" ] } ] }, "box_7": { "description": "Total value of purchases and all other inputs excluding VAT", "total": 3000.0, "exact_total": 3000.0, "components": [ { "label": "Input VAT on standard-rated domestic purchases", "total": 3000.0, "exact_total": 3000.0, "transaction_count": 1, "transaction_ids": [ "P001" ] } ] }, "box_8": { "description": "Total value of all supplies of goods to other EC member states", "total": 0.0, "exact_total": 0.0, "components": [] }, "box_9": { "description": "Total value of all acquisitions of goods from other EC member states", "total": 0.0, "exact_total": 0.0, "components": [] } } }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/vat-returns" } }
Amounts in the request and response are pounds. box_5 is box_3 minus box_4; boxes 6–9 are whole pounds as required for VAT Returns. breakdown shows which transaction IDs contributed to each box.
This calculation does not file a return with HMRC. It validates and calculates supplied transaction data.
Error responses
400 — missing required top-level objects.
{"error":{"code":"bad_request","message":"Request body must contain company, period, and transactions.","documentation_url":"https://docs.govdata.dev/errors/bad_request"}}
400 — well-formed JSON that fails VAT validation.
{"error":{"code":"validation_error","message":"Request contains invalid data.","documentation_url":"https://docs.govdata.dev/errors/validation_error","details":[{"field":"transactions[0]","code":"AMOUNT_MISMATCH","message":"Transaction S001: net_amount (100.0) + vat_amount (20.0) = 120.0, but gross_amount is 999.0."}]}}
422 — a valid fuel-scale request predates the earliest verified HMRC table.
{"error":{"code":"fuel_scale_data_unavailable","message":"Fuel scale charge data is available from 1 May 2024 (HMRC Notice 700/64). Return period starting 2024-01-01 begins before the earliest verified table (effective 2024-05-01) for CO2 band 120, petrol_or_diesel, 3-month accounting period.","documentation_url":"https://docs.govdata.dev/errors/fuel_scale_data_unavailable"}}
VAT Return data notes
Coverage and cadence: implements the UK nine-box VAT Return rules and the seeded HMRC fuel-scale tables. Rule changes and new fuel-scale periods are reviewed when HMRC publishes them; this is calculation software, not a live HMRC ledger.
Licence and attribution: rules are derived from HMRC VAT Returns guidance under the Open Government Licence v3.0. Retain your original records and obtain professional advice for filing decisions.
Partial exemption, Flat Rate Scheme, reverse charge, bad-debt relief, credit notes, fuel scale charges, and capital-goods inputs depend on correctly classified transactions. The endpoint cannot determine classification from free text and does not connect to Making Tax Digital.
Employer Cost Calculator
Calculate the total cost to an employer of hiring staff. Includes gross salary, employer National Insurance contributions, and workplace pension. Supports multiple employees at the same salary and an opt-in Employment Allowance.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
annual_salary |
number | Yes | Gross annual salary in GBP |
tax_year |
string | No | Tax year (e.g. "2025-26"). Defaults to current year. |
pension_rate |
number | No | Employer pension rate as decimal (e.g. 0.03 for 3%). Default: 0.03 |
num_employees |
integer | No | Number of employees at this salary. Default: 1 |
employment_allowance |
boolean | No | Self-attest eligibility and apply the tax year's allowance once against total employer secondary Class 1 NI, floored at zero. Default: false |
curl -X POST -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"annual_salary": 45000, "pension_rate": 0.05, "num_employees": 3, "employment_allowance": true}' \ "https://api.govdata.dev/v1/tax/employer-cost/calculate"
uri = URI("https://api.govdata.dev/v1/tax/employer-cost/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = { annual_salary: 45000, pension_rate: 0.05, num_employees: 3, employment_allowance: true }.to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/employer-cost/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={"annual_salary": 45000, "pension_rate": 0.05, "num_employees": 3, "employment_allowance": True} )
const response = await fetch( "https://api.govdata.dev/v1/tax/employer-cost/calculate", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ annual_salary: 45000, pension_rate: 0.05, num_employees: 3, employment_allowance: true }) } );
Example response
{ "data": { "tax_year": "2025-26", "per_employee": { "annual_salary": 45000.0, "employer_ni": 2500.0, "employer_ni_breakdown": [{ "from": 5000, "to": 45000, "rate": 0.15, "amount": 6000.0 }], "employer_pension": 2250.0, "pension_rate": 0.05, "total_cost": 49750.0 }, "num_employees": 3, "employer_ni_before_allowance": 18000.0, "employment_allowance_applied": 10500.0, "total_annual_cost": 149250.0, "monthly_cost": 12437.5 }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0" } }
Eligibility is not inferred from these inputs. Set employment_allowance: true only after checking the employer is eligible. GOV.UK confirms that from April 2025 employers with more than £100,000 of Class 1 NI liability can apply; other exclusions still apply. See Employment Allowance eligibility.
VAT
List VAT rates
Returns effective UK standard, reduced, and zero VAT rates plus Flat Rate Scheme categories for billing systems, commerce platforms, and finance teams. Use it to label invoice tax choices or validate the rate effective for a historical tax year.
/v1/tax/vat/rates/:tax_year
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
tax_year |
string | No | current date | Optional path tax year in YYYY-YY format; the endpoint chooses rates effective at that year end. |
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/tax/vat/rates/2025-26"
uri = URI("https://api.govdata.dev/v1/tax/vat/rates/2025-26") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/tax/vat/rates/2025-26", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/tax/vat/rates/2025-26", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": { "tax_year": "2025-26", "rates": [ { "name": "reduced", "label": "Reduced Rate", "rate": 0.05, "effective_date": "1994-04-01", "description": "Some goods and services, e.g. home energy and children's car seats" }, { "name": "standard", "label": "Standard Rate", "rate": 0.2, "effective_date": "2011-01-04", "description": "Most goods and services" }, { "name": "zero", "label": "Zero Rate", "rate": 0.0, "effective_date": "1973-04-01", "description": "Zero-rated goods and services, e.g. most food and children's clothes" } ], "flat_rate_schemes": [ { "business_type": "Accountancy or book-keeping", "rate": 0.145 }, { "business_type": "Advertising", "rate": 0.11 }, { "business_type": "Agricultural services", "rate": 0.11 }, { "business_type": "Any other activity not listed elsewhere", "rate": 0.12 }, { "business_type": "Architect, civil and structural engineer or surveyor", "rate": 0.145 }, { "business_type": "Boarding or care of animals", "rate": 0.12 }, { "business_type": "Business services not listed elsewhere", "rate": 0.12 }, { "business_type": "Catering services including restaurants and takeaways from 1 April 2022", "rate": 0.125 }, { "business_type": "Computer and IT consultancy or data processing", "rate": 0.145 }, { "business_type": "Computer repair services", "rate": 0.105 }, { "business_type": "Entertainment or journalism", "rate": 0.125 }, { "business_type": "Estate agency or property management services", "rate": 0.12 }, { "business_type": "Farming or agriculture not listed elsewhere", "rate": 0.065 }, { "business_type": "Film, radio, television or video production", "rate": 0.13 }, { "business_type": "Financial services", "rate": 0.135 }, { "business_type": "Forestry or fishing", "rate": 0.105 }, { "business_type": "General building or construction services", "rate": 0.095 }, { "business_type": "Hairdressing or other beauty treatment services", "rate": 0.13 }, { "business_type": "Hiring or renting goods", "rate": 0.095 }, { "business_type": "Hotel or accommodation from 1 April 2022", "rate": 0.105 }, { "business_type": "Investigation or security", "rate": 0.12 }, { "business_type": "Labour-only building or construction services", "rate": 0.145 }, { "business_type": "Laundry or dry-cleaning services", "rate": 0.12 }, { "business_type": "Lawyer or legal services", "rate": 0.145 }, { "business_type": "Library, archive, museum or other cultural activity", "rate": 0.095 }, { "business_type": "Limited cost trader", "rate": 0.165 }, { "business_type": "Management consultancy", "rate": 0.14 }, { "business_type": "Manufacturing fabricated metal products", "rate": 0.105 }, { "business_type": "Manufacturing food", "rate": 0.09 }, { "business_type": "Manufacturing not listed elsewhere", "rate": 0.095 }, { "business_type": "Manufacturing yarn, textiles or clothing", "rate": 0.09 }, { "business_type": "Membership organisation", "rate": 0.08 }, { "business_type": "Mining or quarrying", "rate": 0.1 }, { "business_type": "Packaging", "rate": 0.09 }, { "business_type": "Photography", "rate": 0.11 }, { "business_type": "Post offices", "rate": 0.05 }, { "business_type": "Printing", "rate": 0.085 }, { "business_type": "Publishing", "rate": 0.11 }, { "business_type": "Pubs from 1 April 2022", "rate": 0.065 }, { "business_type": "Real estate activity not listed elsewhere", "rate": 0.14 }, { "business_type": "Repairing personal or household goods", "rate": 0.1 }, { "business_type": "Repairing vehicles", "rate": 0.085 }, { "business_type": "Retailing food, confectionery, tobacco, newspapers or children’s clothing", "rate": 0.04 }, { "business_type": "Retailing not listed elsewhere", "rate": 0.075 }, { "business_type": "Retailing pharmaceuticals, medical goods, cosmetics or toiletries", "rate": 0.08 }, { "business_type": "Retailing vehicles or fuel", "rate": 0.065 }, { "business_type": "Secretarial services", "rate": 0.13 }, { "business_type": "Social work", "rate": 0.11 }, { "business_type": "Sport or recreation", "rate": 0.085 }, { "business_type": "Transport or storage, including couriers, freight, removals and taxis", "rate": 0.1 }, { "business_type": "Travel agency", "rate": 0.105 }, { "business_type": "Veterinary medicine", "rate": 0.11 }, { "business_type": "Wholesaling agricultural products", "rate": 0.08 }, { "business_type": "Wholesaling food", "rate": 0.075 }, { "business_type": "Wholesaling not listed elsewhere", "rate": 0.085 } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/vat-rates", "tax_year": "2025-26" } }
Rates are decimals: 0.20 means 20%. effective_date is the date a VAT rate began; Flat Rate Scheme percentage fields are percentage points, not decimals.
Error responses
404 — the requested tax year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
Filter Flat Rate Scheme percentages
Returns HMRC Flat Rate Scheme business categories effective on a date, optionally narrowed to one stable code. Populate an onboarding category selector or calculate the first-year discount for a small VAT-registered business.
/v1/tax/vat/flat-rate-percentages
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
effective_date |
date | No | today | ISO 8601 date used in the response and for future effective-dating. |
category |
string | No | all categories | Exact snake-case category code returned by this endpoint. |
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/tax/vat/flat-rate-percentages?effective_date=2026-08-06&category=accountancy_or_book-keeping"
uri = URI("https://api.govdata.dev/v1/tax/vat/flat-rate-percentages?effective_date=2026-08-06&category=accountancy_or_book-keeping") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/tax/vat/flat-rate-percentages?effective_date=2026-08-06&category=accountancy_or_book-keeping", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/tax/vat/flat-rate-percentages?effective_date=2026-08-06&category=accountancy_or_book-keeping", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": { "effective_date": "2026-08-06", "last_updated": "2026-08-05T21:24:19Z", "source": "HMRC Notice 733", "categories": [ { "code": "accountancy_or_book-keeping", "description": "Accountancy or book-keeping", "percentage": 14.5, "first_year_percentage": 13.5 } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/vat-flat-rate-scheme/how-much-you-pay" } }
percentage is the normal Flat Rate Scheme percentage; first_year_percentage applies the one-point first-year discount. This endpoint does not test scheme eligibility.
Error responses
400 — effective_date is not ISO 8601.
{"error":{"code":"invalid_date_format","message":"Parameter 'effective_date' must be a valid ISO 8601 date (YYYY-MM-DD). Received: '06-08-2026'.","documentation_url":"https://docs.govdata.dev/errors/invalid_date_format"}}
404 — the category code is unknown.
{"error":{"code":"category_not_found","message":"No flat rate category found matching 'does_not_exist'. Use GET /vat/flat-rate-percentages without a category filter to see all available categories.","documentation_url":"https://docs.govdata.dev/errors/category_not_found"}}
Calculate VAT
Adds VAT to a net amount or extracts VAT from a VAT-inclusive total for invoice previews, checkout calculations, and bookkeeping imports. Calculate the tax on a £1,000 net service or split a £1,200 gross receipt into net and VAT.
/v1/tax/vat/calculate
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
amount |
number | Yes | — | Pound amount before VAT (exclusive) or including VAT (inclusive). |
rate |
string | No | standard | standard, reduced, or zero. |
direction |
string | No | exclusive | exclusive adds VAT; inclusive extracts VAT from the supplied total. |
curl -X POST "https://api.govdata.dev/v1/tax/vat/calculate" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"amount":1200,"rate":"standard","direction":"inclusive"}'
uri = URI("https://api.govdata.dev/v1/tax/vat/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = JSON.parse('{"amount":1200,"rate":"standard","direction":"inclusive"}').to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/vat/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json=json.loads('{"amount":1200,"rate":"standard","direction":"inclusive"}') )
const response = await fetch("https://api.govdata.dev/v1/tax/vat/calculate", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify(JSON.parse('{"amount":1200,"rate":"standard","direction":"inclusive"}')) });
Response
{ "data": { "net_amount": 1000.0, "vat_amount": 200.0, "total": 1200.0, "rate": 0.2, "rate_name": "standard", "rate_type": "standard", "direction": "inclusive" }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/vat-rates" } }
All monetary fields are pounds. rate is a decimal, while amount outputs are rounded to two decimal places.
Error responses
400 — the required amount field is missing.
{"error":{"code":"missing_parameter","message":"amount is required.","documentation_url":"https://docs.govdata.dev/errors/missing_parameter"}}
422 — direction is outside the supported enum.
{"error":{"code":"invalid_direction","message":"Direction must be 'exclusive' or 'inclusive'.","documentation_url":"https://docs.govdata.dev/errors/invalid_direction"}}
422 — rate is not a recognised VAT rate name.
{"error":{"code":"invalid_rate","message":"VAT rate 'super_reduced' not found","documentation_url":"https://docs.govdata.dev/errors/invalid_rate"}}
VAT data notes
Coverage and cadence: UK VAT reference data covers 2020–21 onward, with the long-running statutory rates' true effective dates retained. HMRC changes are reviewed after fiscal announcements; Flat Rate Scheme categories reflect HMRC Notice 733.
Flat Rate Scheme history: FRS percentages are a current snapshot with no historical dating. Supplying a past tax_year does not return the percentages that applied in that year.
Licence and attribution: source HMRC VAT rates and Flat Rate Scheme guidance, reused under the Open Government Licence v3.0.
The calculator performs arithmetic only: it does not decide whether a supply is standard-, reduced-, zero-rated, exempt, or outside scope. Flat Rate Scheme percentages apply to VAT-inclusive turnover and are not interchangeable with invoice VAT rates.
Capital Gains Tax
List Capital Gains Tax rates
Returns CGT rates by asset type and taxpayer band for tax software, wealth dashboards, and scenario planners. Compare residential-property and other-asset treatment or select the Business Asset Disposal Relief rate for an estimate.
/v1/tax/capital-gains/rates/:tax_year
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
tax_year |
string | No | current tax year | Optional path tax year in YYYY-YY format. |
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/tax/capital-gains/rates/2025-26"
uri = URI("https://api.govdata.dev/v1/tax/capital-gains/rates/2025-26") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/tax/capital-gains/rates/2025-26", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/tax/capital-gains/rates/2025-26", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": { "tax_year": "2025-26", "rates": [ { "asset_type": "residential_property", "taxpayer_band": "basic", "rate": 0.18 }, { "asset_type": "residential_property", "taxpayer_band": "higher", "rate": 0.24 }, { "asset_type": "other_assets", "taxpayer_band": "basic", "rate": 0.18 }, { "asset_type": "other_assets", "taxpayer_band": "higher", "rate": 0.24 }, { "asset_type": "business_asset_disposal", "taxpayer_band": "basic", "rate": 0.14 }, { "asset_type": "business_asset_disposal", "taxpayer_band": "higher", "rate": 0.14 } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/capital-gains-tax/rates", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
Rates are decimals. taxpayer_band is a simplified band selection; a real basic-rate taxpayer may pay CGT at more than one rate when a gain crosses the unused basic-rate band.
Error responses
404 — the requested tax year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
List CGT allowances
Returns the annual exempt amount and Business Asset Disposal Relief lifetime limit for tax-year-aware forms and planning tools. Use it to prefill an individual's exemption or display the relief lifetime ceiling beside a disposal estimate.
/v1/tax/capital-gains/allowances/:tax_year
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
tax_year |
string | No | current tax year | Optional path tax year in YYYY-YY format. |
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/tax/capital-gains/allowances/2025-26"
uri = URI("https://api.govdata.dev/v1/tax/capital-gains/allowances/2025-26") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/tax/capital-gains/allowances/2025-26", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/tax/capital-gains/allowances/2025-26", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": { "tax_year": "2025-26", "allowances": [ { "allowance_type": "annual_exempt_amount", "amount": 3000 }, { "allowance_type": "business_asset_disposal_lifetime", "amount": 1000000 } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/capital-gains-tax/rates", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
Amounts are pounds. The API returns the individual annual exempt amount; trusts can have a different allowance.
Error responses
404 — the requested tax year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
Calculate Capital Gains Tax
Applies the annual exemption and one selected seeded rate to a gain for quick estimates and what-if tools. Estimate tax on a £25,000 residential-property gain or compare the result when the taxpayer band changes.
/v1/tax/capital-gains/calculate
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
gain |
integer | Yes | — | Total gain in pounds before the annual exempt amount. |
asset_type |
string | No | other_assets | residential_property, other_assets, or business_asset_disposal. |
taxpayer_band |
string | No | basic | basic or higher. |
tax_year |
string | No | current tax year | Tax year in YYYY-YY format. |
curl -X POST "https://api.govdata.dev/v1/tax/capital-gains/calculate" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"gain":25000,"asset_type":"residential_property","taxpayer_band":"higher","tax_year":"2025-26"}'
uri = URI("https://api.govdata.dev/v1/tax/capital-gains/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = JSON.parse('{"gain":25000,"asset_type":"residential_property","taxpayer_band":"higher","tax_year":"2025-26"}').to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/capital-gains/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json=json.loads('{"gain":25000,"asset_type":"residential_property","taxpayer_band":"higher","tax_year":"2025-26"}') )
const response = await fetch("https://api.govdata.dev/v1/tax/capital-gains/calculate", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify(JSON.parse('{"gain":25000,"asset_type":"residential_property","taxpayer_band":"higher","tax_year":"2025-26"}')) });
Response
{ "data": { "gain": 25000, "annual_exempt_amount": 3000, "taxable_gain": 22000, "rate": 0.24, "tax": 5280.0, "tax_year": "2025-26", "asset_type": "residential_property", "taxpayer_band": "higher" }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/capital-gains-tax/rates", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
This simplified calculator applies one rate after one annual exemption. It does not account for allowable losses, income using part of the basic-rate band, joint ownership, carried-forward losses, or relief eligibility.
Error responses
400 — the required gain field is missing.
{"error":{"code":"missing_parameter","message":"gain is required.","documentation_url":"https://docs.govdata.dev/errors/missing_parameter"}}
404 — tax_year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
422 — asset_type is unsupported.
{"error":{"code":"invalid_asset_type","message":"Asset type must be one of: residential_property, other_assets, business_asset_disposal","documentation_url":"https://docs.govdata.dev/errors/invalid_asset_type"}}
422 — taxpayer_band is unsupported.
{"error":{"code":"invalid_taxpayer_band","message":"Taxpayer band must be 'basic' or 'higher'.","documentation_url":"https://docs.govdata.dev/errors/invalid_taxpayer_band"}}
CGT data notes
Coverage and cadence: tax years 2020–21 through 2026–27, reviewed annually and after fiscal events. Source HMRC CGT rates under the Open Government Licence v3.0.
A loaded but unsupported year such as 1999-00 returns 404 tax_year_not_covered: “Capital gains rates is covered for 2020-21 to 2026-27; 1999-00 is not covered.” A genuinely unknown identifier such as 1888-89 returns invalid_tax_year.
The equivalent messages are “Dividend rates is covered for 2020-21 to 2026-27; 1999-00 is not covered.” and “Corporation tax rates is covered for 2020-21 to 2026-27; 1999-00 is not covered.”
Rates and relief rules can change within a tax year; the endpoint exposes the annual values seeded for each supported year. The calculator is an estimate and does not establish residence, disposal date, relief qualification, or filing obligations.
Dividend Tax
List dividend rates
Returns the dividend allowance and rates for each income-tax band for payroll-adjacent tools, investor dashboards, and tax planners. Prefill a tax-year calculator or explain the marginal tax rate on a planned distribution.
/v1/tax/dividends/rates/:tax_year
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
tax_year |
string | No | current tax year | Optional path tax year in YYYY-YY format. |
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/tax/dividends/rates/2025-26"
uri = URI("https://api.govdata.dev/v1/tax/dividends/rates/2025-26") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/tax/dividends/rates/2025-26", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/tax/dividends/rates/2025-26", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": { "tax_year": "2025-26", "dividend_allowance": 500, "rates": [ { "band": "basic", "rate": 0.0875 }, { "band": "higher", "rate": 0.3375 }, { "band": "additional", "rate": 0.3935 } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/tax-on-dividends", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
The allowance is a zero-rate band, not a deduction from total income; dividends still count toward the taxpayer's income-tax bands.
Error responses
404 — the requested tax year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
Calculate dividend tax
Subtracts the dividend allowance and applies one selected band rate for quick distribution estimates. Estimate tax on a £10,000 dividend for a higher-rate taxpayer or compare band-specific outcomes in a planning interface.
/v1/tax/dividends/calculate
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
dividend_income |
integer | Yes | — | Annual dividend income in pounds. |
taxpayer_band |
string | No | basic | basic, higher, or additional. |
tax_year |
string | No | current tax year | Tax year in YYYY-YY format. |
curl -X POST "https://api.govdata.dev/v1/tax/dividends/calculate" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"dividend_income":10000,"taxpayer_band":"higher","tax_year":"2025-26"}'
uri = URI("https://api.govdata.dev/v1/tax/dividends/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = JSON.parse('{"dividend_income":10000,"taxpayer_band":"higher","tax_year":"2025-26"}').to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/dividends/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json=json.loads('{"dividend_income":10000,"taxpayer_band":"higher","tax_year":"2025-26"}') )
const response = await fetch("https://api.govdata.dev/v1/tax/dividends/calculate", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify(JSON.parse('{"dividend_income":10000,"taxpayer_band":"higher","tax_year":"2025-26"}')) });
Response
{ "data": { "dividend_income": 10000, "allowance": 500, "taxable_dividends": 9500, "rate": 0.3375, "tax": 3206.25, "tax_year": "2025-26", "taxpayer_band": "higher" }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/tax-on-dividends", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
The simplified result applies one rate to all taxable dividends. In a full tax calculation, dividends sit on top of other income and may span bands.
Error responses
400 — the required dividend_income field is missing.
{"error":{"code":"missing_parameter","message":"dividend_income is required.","documentation_url":"https://docs.govdata.dev/errors/missing_parameter"}}
404 — tax_year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
422 — taxpayer_band is unsupported.
{"error":{"code":"invalid_taxpayer_band","message":"Taxpayer band must be one of: basic, higher, additional","documentation_url":"https://docs.govdata.dev/errors/invalid_taxpayer_band"}}
Dividend data notes
Coverage and cadence: tax years 2020–21 through 2026–27, reviewed annually and after fiscal events. Source HMRC tax on dividends under the Open Government Licence v3.0.
The calculator excludes other income, personal allowance tapering, Scottish non-dividend bands, and band-splitting. UK dividend rates apply UK-wide, but the band occupied depends on the taxpayer's full income.
Student Loans
List repayment thresholds
Returns annual thresholds and deduction rates for undergraduate Plans 1, 2, 4 and 5 plus postgraduate loans, for payroll systems, salary calculators, and graduate budgeting tools. Select the correct plan threshold or show why two borrowers on the same salary repay different amounts.
/v1/tax/student-loan/thresholds/:tax_year
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
tax_year |
string | No | current tax year | Optional path tax year in YYYY-YY format. |
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/tax/student-loan/thresholds/2025-26"
uri = URI("https://api.govdata.dev/v1/tax/student-loan/thresholds/2025-26") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/tax/student-loan/thresholds/2025-26", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/tax/student-loan/thresholds/2025-26", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": { "tax_year": "2025-26", "thresholds": [ { "plan_type": "plan_1", "annual_threshold": 24990, "rate": 0.09 }, { "plan_type": "plan_2", "annual_threshold": 27295, "rate": 0.09 }, { "plan_type": "plan_4", "annual_threshold": 31395, "rate": 0.09 }, { "plan_type": "plan_5", "annual_threshold": 25000, "rate": 0.09 }, { "plan_type": "postgraduate", "annual_threshold": 21000, "rate": 0.06 } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC / SLC", "source_url": "https://www.gov.uk/repaying-your-student-loan/what-you-pay", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
Thresholds are annualised pounds and rates are decimals. Payroll deductions are normally calculated per pay period, so annual estimates can differ slightly through rounding or variable pay.
Error responses
404 — the requested tax year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
Calculate student-loan repayments
Calculates annual repayments for one or more loan plans and totals them, for take-home-pay products and payroll forecasts. Model concurrent Plan 2 and postgraduate deductions on a £50,000 salary or compare repayment plans for a job offer.
/v1/tax/student-loan/calculate
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
annual_income |
integer | Yes | — | Annual earnings used for the estimate, in pounds. |
plan_types |
array or CSV string | Yes | — | One or more of plan_1, plan_2, plan_4, plan_5, postgraduate. |
tax_year |
string | No | current tax year | Tax year in YYYY-YY format. |
curl -X POST "https://api.govdata.dev/v1/tax/student-loan/calculate" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"annual_income":50000,"plan_types":["plan_2","postgraduate"],"tax_year":"2025-26"}'
uri = URI("https://api.govdata.dev/v1/tax/student-loan/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = JSON.parse('{"annual_income":50000,"plan_types":["plan_2","postgraduate"],"tax_year":"2025-26"}').to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/student-loan/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json=json.loads('{"annual_income":50000,"plan_types":["plan_2","postgraduate"],"tax_year":"2025-26"}') )
const response = await fetch("https://api.govdata.dev/v1/tax/student-loan/calculate", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify(JSON.parse('{"annual_income":50000,"plan_types":["plan_2","postgraduate"],"tax_year":"2025-26"}')) });
Response
{ "data": { "annual_income": 50000, "tax_year": "2025-26", "repayments": [ { "plan_type": "plan_2", "threshold": 27295, "rate": 0.09, "amount": 2043.45 }, { "plan_type": "postgraduate", "threshold": 21000, "rate": 0.06, "amount": 1740.0 } ], "total_repayment": 3783.45 }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC / SLC", "source_url": "https://www.gov.uk/repaying-your-student-loan/what-you-pay", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
Each plan is calculated independently above its own threshold; total_repayment is the sum. Actual payroll uses pay-period thresholds and HMRC rounding.
Error responses
400 — the required annual_income field is missing.
{"error":{"code":"missing_parameter","message":"annual_income is required.","documentation_url":"https://docs.govdata.dev/errors/missing_parameter"}}
404 — tax_year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
422 — a plan type is unsupported.
{"error":{"code":"invalid_plan_type","message":"Invalid plan type(s): plan_9. Valid types: plan_1, plan_2, plan_4, plan_5, postgraduate","documentation_url":"https://docs.govdata.dev/errors/invalid_plan_type"}}
422 — plan_types is missing or empty.
{"error":{"code":"missing_plan_types","message":"At least one plan type is required. Valid types: plan_1, plan_2, plan_4, plan_5, postgraduate","documentation_url":"https://docs.govdata.dev/errors/missing_plan_types"}}
Student-loan data notes
Coverage and cadence: thresholds are loaded for 2025–26 and 2026–27 and reviewed each tax year. Source HMRC and Student Loans Company repayment guidance under the Open Government Licence v3.0.
This is an annual estimate, not a loan balance or payoff calculation. It excludes interest, overseas repayment schedules, refunds, employer payroll timing, and stop notices; postgraduate and undergraduate deductions can run concurrently.
Pension Allowances
List pension contribution allowances
Returns the annual allowance, Money Purchase Annual Allowance, and tapered-allowance income thresholds for pension platforms, advisers, and contribution-limit warnings. Prefill a tax-year planning form or flag when adjusted income may trigger tapering.
/v1/tax/pension/allowances/:tax_year
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
tax_year |
string | No | current tax year | Optional path tax year in YYYY-YY format. |
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/tax/pension/allowances/2025-26"
uri = URI("https://api.govdata.dev/v1/tax/pension/allowances/2025-26") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/tax/pension/allowances/2025-26", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/tax/pension/allowances/2025-26", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": { "tax_year": "2025-26", "allowances": [ { "allowance_type": "annual", "amount": 60000 }, { "allowance_type": "mpaa", "amount": 10000 }, { "allowance_type": "tapered_threshold_income", "amount": 200000 }, { "allowance_type": "tapered_adjusted_income", "amount": 260000 }, { "allowance_type": "minimum_tapered", "amount": 10000 } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/tax-on-your-private-pension/annual-allowance", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
tapered_threshold_income and tapered_adjusted_income are different statutory tests. MPAA applies after flexible access; the endpoint does not determine whether it has been triggered.
Error responses
404 — the requested tax year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
Pension data notes
Coverage and cadence: allowances are loaded for 2025–26 and 2026–27 and reviewed annually. Source HMRC private-pension annual-allowance guidance under the Open Government Licence v3.0.
Reference data only: there is no pension calculator. Carry-forward, defined-benefit pension input amounts, MPAA triggering, protected allowances, and taper calculations require personal history not accepted by this endpoint.
Corporation Tax
List Corporation Tax rates
Returns the small-profits rate, main rate, marginal-relief fraction, and profit limits for company tax software, founder planning tools, and finance teams. Display the applicable band or explain the marginal-relief range before calculating an estimate.
/v1/tax/corporation/rates/:tax_year
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
tax_year |
string | No | current tax year | Optional path tax year in YYYY-YY format. |
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/tax/corporation/rates/2025-26"
uri = URI("https://api.govdata.dev/v1/tax/corporation/rates/2025-26") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/tax/corporation/rates/2025-26", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/tax/corporation/rates/2025-26", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": { "tax_year": "2025-26", "rates": [ { "rate_type": "small_profits", "rate": 0.19, "lower_limit": 0, "upper_limit": 50000 }, { "rate_type": "main", "rate": 0.25, "lower_limit": 250000 }, { "rate_type": "marginal_relief_fraction", "rate": 0.015, "lower_limit": 50000, "upper_limit": 250000 } ] }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/corporation-tax-rates", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
Limits are pounds for a standalone company with a 12-month accounting period. They are reduced for associated companies and short accounting periods.
Error responses
404 — the requested tax year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
Calculate Corporation Tax
Applies the small-profits rate, main rate, or marginal relief to annual taxable profit for forecasts and scenario tools. Estimate tax on £100,000 profit or show the effective rate within the marginal-relief band.
/v1/tax/corporation/calculate
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
profit |
integer | Yes | — | Annual taxable profit in pounds. |
tax_year |
string | No | current tax year | Tax year in YYYY-YY format. |
curl -X POST "https://api.govdata.dev/v1/tax/corporation/calculate" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"profit":100000,"tax_year":"2025-26"}'
uri = URI("https://api.govdata.dev/v1/tax/corporation/calculate") req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json") req["Authorization"] = "Bearer YOUR_API_KEY" req.body = JSON.parse('{"profit":100000,"tax_year":"2025-26"}').to_json res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.post( "https://api.govdata.dev/v1/tax/corporation/calculate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json=json.loads('{"profit":100000,"tax_year":"2025-26"}') )
const response = await fetch("https://api.govdata.dev/v1/tax/corporation/calculate", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify(JSON.parse('{"profit":100000,"tax_year":"2025-26"}')) });
Response
{ "data": { "profit": 100000, "tax_year": "2025-26", "rate_type": "marginal_relief", "tax": 22750.0, "effective_rate": 0.2275, "marginal_relief": 2250.0 }, "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "HMRC", "source_url": "https://www.gov.uk/corporation-tax-rates", "last_updated": "2025-04-06", "tax_year": "2025-26" } }
marginal_relief is the amount deducted from tax at the main rate. Thresholds assume one standalone company and a 12-month period.
Error responses
400 — the required profit field is missing.
{"error":{"code":"missing_parameter","message":"profit is required.","documentation_url":"https://docs.govdata.dev/errors/missing_parameter"}}
404 — tax_year is not loaded.
{"error":{"code":"invalid_tax_year","message":"Tax year '1888-89' not found. Use format YYYY-YY (e.g. 2025-26).","documentation_url":"https://docs.govdata.dev/errors/invalid_tax_year"}}
Corporation Tax data notes
Coverage and cadence: tax years 2020–21 through 2026–27, reviewed annually and after fiscal events. Source HMRC Corporation Tax rates under the Open Government Licence v3.0.
The calculator excludes associated-company threshold division, short periods, ring-fence profits, exempt distributions, augmented profits, losses, reliefs, and accounting-period apportionment. It is an estimate, not a CT600 computation.
Data Coverage
| Source | HMRC / GOV.UK |
| Date range | Income Tax: 1990-91 to 2026-27 (37 years); National Insurance: 1999-00 to 2026-27 (28 years). VAT, Capital Gains Tax, dividend tax, and Corporation Tax: 2020-21 to 2026-27. |
| Records | 7 tax years across VAT/CGT/dividends/Corporation Tax; 37 years of Income Tax and 28 years of National Insurance history |
| Updated | Annually (after Budget) |
| Limitations | VAT, CGT, dividend tax, and Corporation Tax rates before 2020-21 not yet available. Student loan and pension allowance history starts at 2025-26. |