The Tax Brief real effective rates for 111+ countries — bi-weekly, free.
API GUIDE

Tax API for HR Software — Compensation & Payroll Context

CountryTaxCalc Research Team · About Updated July 2026
Tax data in examples is for informational and product integration purposes only, sourced from official government tax authorities. Consumer-facing products must include appropriate disclaimers — see the API Terms of Service and Legal Disclaimer.

HR software use cases

Income tax data adds significant context to HR and compensation workflows. The most common integrations:

  • Offer letter generation — show candidates their estimated take-home pay alongside the gross salary in their offer
  • Job listing pages — display after-tax salary for each country where a role is available
  • Compensation benchmarking — compare total compensation packages across countries on a net-income basis
  • Employee pay portals — let employees see their own estimated take-home breakdown on demand
  • Headcount planning — quickly model after-tax compensation for new hire locations before finalising packages
  • Equity compensation modelling — combine base salary take-home with estimated tax treatment of RSUs or options

All of these use the same core endpoint — POST /api/v1/calculate — which is available on the free tier. The use case complexity determines whether you need higher-tier features like the summary endpoint or historical data.

Offer letter take-home calculation

When generating an offer letter, a take-home pay estimate alongside the gross salary makes the offer more concrete and easier for candidates to evaluate. Here's a Node.js function that calculates take-home for an offer:

// server-side only
const API_KEY = process.env.COUNTRYTAXCALC_API_KEY;

async function getOfferTakeHome(grossSalary, countryCode, currencyCode = null) {
  const payload = {
    income: grossSalary,
    country: countryCode
  };
  if (currencyCode) payload.currency = currencyCode;

  const resp = await fetch(
    "https://api.countrytaxcalc.com/api/v1/calculate",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-API-Key": API_KEY
      },
      body: JSON.stringify(payload)
    }
  );

  if (!resp.ok) {
    throw new Error(`Tax API error: ${resp.status}`);
  }

  const data = await resp.json();
  const { totals, metadata } = data;

  return {
    grossSalary,
    netIncome: totals.net_income,
    monthlyNet: totals.monthly_net_income,
    effectiveRate: totals.effective_tax_rate,
    currency: data.currency,
    currencySymbol: data.currency_symbol,
    confidence: metadata.accuracy_confidence,
    dataSource: metadata.data_source,
    isEstimate: metadata.accuracy_confidence < 0.9
  };
}

// Generate offer context for a UK-based role
const offer = await getOfferTakeHome(75000, "GB");
console.log(`Offer: £${offer.grossSalary.toLocaleString()} gross`);
console.log(`Estimated take-home: £${offer.netIncome.toLocaleString()} net (£${offer.monthlyNet.toLocaleString()}/month)`);
console.log(`Effective tax rate: ${offer.effectiveRate}%`);
if (offer.isEstimate) console.log("Note: Estimate only — individual circumstances may vary");

Offer letter template language

When surfacing tax estimates in an offer letter, use appropriately qualified language:

  • Do: "Based on your base salary of £75,000, your estimated take-home pay is approximately £52,800/year (£4,400/month) before any personal deductions."
  • Do: "These are estimates based on standard tax rates. Your actual take-home will depend on your personal circumstances, pension contributions, and other deductions."
  • Don't: Present the figure as a guarantee or precise calculation without qualification.

Compensation benchmarking across countries

When a role is open in multiple countries, net income comparison makes packages directly comparable. A £80,000 UK offer and a $110,000 US (California) offer both need to be evaluated on take-home, not gross.

// Compare compensation packages across locations
async function benchmarkCompensation(packages) {
  // packages: [{gross, country, currency?, jurisdiction?, label}]

  const results = await Promise.all(
    packages.map(async pkg => {
      const payload = {
        income: pkg.gross,
        country: pkg.country
      };
      if (pkg.currency) payload.currency = pkg.currency;
      if (pkg.jurisdiction) payload.jurisdiction = pkg.jurisdiction;

      const resp = await fetch(
        "https://api.countrytaxcalc.com/api/v1/calculate",
        {
          method: "POST",
          headers: { "Content-Type": "application/json", "X-API-Key": API_KEY },
          body: JSON.stringify(payload)
        }
      );

      const data = await resp.json();
      return {
        label: pkg.label || data.country,
        gross: pkg.gross,
        net: data.totals.net_income,
        monthly: data.totals.monthly_net_income,
        effectiveRate: data.totals.effective_tax_rate,
        currency: data.currency,
        symbol: data.currency_symbol,
        source: data.metadata.data_source
      };
    })
  );

  results.sort((a, b) => {
    // Note: cross-currency comparison requires a common currency baseline
    // Use currency conversion if comparing different currencies
    return b.net - a.net;
  });

  return results;
}

// Example: compare three offers for the same role
const packages = [
  { gross: 80000, country: "GB", label: "London (GBP)" },
  { gross: 110000, country: "US", jurisdiction: "CA", currency: "USD", label: "San Francisco (USD)" },
  { gross: 95000, country: "DE", currency: "EUR", label: "Berlin (EUR)" }
];

const comparison = await benchmarkCompensation(packages);
comparison.forEach((c, i) => {
  console.log(`#${i+1} ${c.label}: ${c.symbol}${c.net.toLocaleString()} net (${c.effectiveRate}% effective)`);
});

For cross-currency comparisons, pass the same currency to all requests (e.g. "currency": "USD") so the API converts each package to a common baseline before calculating, making effective rates directly comparable.

Employee pay portal integration

An employee portal can show each employee their estimated take-home breakdown on their pay or compensation page. The key design considerations:

What to display

  • Annual and monthly net income
  • Effective tax rate ("You're in the X% effective rate band")
  • A line-item breakdown of income tax and social contributions
  • The tax year and data source for transparency
  • A clear disclaimer that these are estimates

What not to display

  • Tax brackets and thresholds as though they're authoritative payslip figures — they're not
  • The calculation as a substitute for official payslip data from the payroll system
  • Confidence as a percentage without explanation
// Employee portal API route (Express.js)
// Employees only see their own salary data — enforce auth middleware before this
router.get("/my-tax-estimate", requireAuth, async (req, res) => {
  const employee = await getEmployeeByUserId(req.user.id);

  const payload = {
    income: employee.annualGrossSalary,
    country: employee.countryCode
  };
  if (employee.stateCode) payload.jurisdiction = employee.stateCode;

  const resp = await fetch(
    "https://api.countrytaxcalc.com/api/v1/calculate",
    {
      method: "POST",
      headers: { "Content-Type": "application/json", "X-API-Key": API_KEY },
      body: JSON.stringify(payload)
    }
  );

  const taxData = await resp.json();

  // Return only what the employee needs — don't expose full API response
  res.json({
    grossSalary: employee.annualGrossSalary,
    currency: taxData.currency,
    currencySymbol: taxData.currency_symbol,
    estimatedNetIncome: taxData.totals.net_income,
    estimatedMonthlyNet: taxData.totals.monthly_net_income,
    effectiveTaxRate: taxData.totals.effective_tax_rate,
    takeHomePercentage: taxData.totals.take_home_percentage,
    incomeTax: taxData.breakdown.national_income_tax.amount,
    socialContributions: taxData.breakdown.social_contributions,
    taxYear: taxData.tax_year,
    dataSource: taxData.metadata.data_source,
    isEstimate: true  // always true — direct users to payroll for actuals
  });
});

Multi-country payroll context

For companies with distributed or remote-first workforces, the API is useful for:

  • Pre-hiring compensation research — before posting a role in a new country, understand what a given gross salary means in take-home terms
  • Pay equity analysis — compare whether employees in different countries are receiving equivalent net compensation for equivalent roles
  • Contractor vs. employee modelling — for EOR (Employer of Record) decisions, model the difference in take-home between direct employment and contractor structures
  • Annual review preparation — refresh take-home estimates before compensation reviews to check for inflation erosion in real take-home pay
Historical data (Growth+): Growth, Pro, and Enterprise plans can pass "tax_year": 2024 in the request to get prior-year calculations. This is useful for year-over-year analysis — for example, comparing whether a salary increase kept pace with changes in tax thresholds or inflation, or auditing what take-home pay was in a prior year.

API tier upgrade path for HR use cases

Most HR integrations start on Free or Starter and upgrade as usage grows:

Use case Recommended tier Key features needed
Offer letter take-home for <50 hires/month Free POST /calculate
Job listing page with per-country take-home Starter ($19/mo) 50,000 req/month + /countries/{code}
Employee portal with year-over-year view Growth ($49/mo) Historical tax years + GET /summary
Compensation benchmarking across all 111 countries Growth ($49/mo) GET /summary (single call, all countries ranked)
Real-time offer comparison across up to 20 countries Pro ($149/mo) POST /compare with savings analysis
High-volume HRIS integration (>500k req/month) Pro or Enterprise Volume + SLA + dedicated support

Compliance and disclaimers

HR applications surfacing tax estimates have specific compliance obligations:

Required disclaimer (API Terms of Service)

Any consumer-facing product — including an employee portal — must include a disclaimer that estimates are approximate and for informational purposes only. Recommended language:

Tax estimates are calculated using standard tax rates for the selected country and are for informational purposes only. Actual take-home pay will depend on your individual circumstances, including pension contributions, tax reliefs, filing status, and other deductions. Consult a qualified tax professional for advice specific to your situation. These figures are not a substitute for your official payslip.

Data privacy

The CountryTaxCalc API does not store, log, or process income values after the calculation is returned. No PII is retained. See the privacy policy for full details. For your own application, ensure salary data submitted to your proxy is handled in accordance with your HR data retention policy and applicable employment law (GDPR for EU employees, etc.).

Not a payroll system

The API is a tax estimation tool — it is not a payroll calculation engine. It should never be used to determine actual payroll deductions, issue payslips, or comply with payroll tax reporting obligations. For official payroll, use a licensed payroll provider.

Frequently asked questions

Q: Can the API handle US federal + state tax together?

Yes. Pass "country": "US" and a "jurisdiction" field with the two-letter state code (e.g. "CA" for California, "TX" for Texas). The response includes a combined federal + state breakdown, including Social Security and Medicare, in a single calculation. Use GET /api/v1/countries/US (Starter+) to retrieve all supported state codes.

Q: Does the API calculate employer costs (not just employee take-home)?

The API currently models employee-side tax only — what the employee receives after their deductions. It does not model employer payroll taxes, employer social contributions, or total employment costs. If you need employer cost modelling (for headcount planning), use the net income and effective rate figures as a proxy for employee compensation context, and apply your own employer burden estimates on top.

Q: What's the best approach for showing take-home pay on job listings?

For a job listing page, pre-calculate and cache the net income for each country where the role is available at the listed salary. Call POST /calculate at build time or on first load and cache the result for 24 hours. This makes the page fast and uses minimal API quota. If salary ranges are shown (e.g. £60k–£80k), calculate for the midpoint and note it's approximate.

Q: How do I handle confidential salary data securely?

The API does not store or log income values submitted to it. The income you pass is used for the calculation only and is not retained. For your application: ensure API calls are made server-side (not client-side), log income data only as required for your own compliance purposes, and ensure your proxy validates that users can only query their own salary data if your portal is employee-facing.

Q: Can I integrate this with an HRIS like Workday, BambooHR, or Rippling?

Yes — the API is a standard REST endpoint. You can integrate it anywhere you can make HTTP requests: a custom Workday integration script, a BambooHR webhook handler, a Rippling app, or a standalone middleware service. The typical pattern is a server-side service that reads salary and location data from your HRIS and enriches it with take-home pay from the tax API.

Q: What tier do I need for a compensation benchmarking tool covering all 111 countries?

For a tool that compares a salary across all 111 countries, Growth plan ($49/month) gives you access to GET /api/v1/summary — a single call that returns all 111 countries ranked at a given income level. For drill-down breakdowns on individual countries, combine with POST /calculate. The loop approach with POST /calculate works on Starter or even Free, but consumes one request per country.

Ready to integrate? 1,000 requests/month free. No credit card required.
Get your free API key →