Skip to content
Takehome
  • Calculators

    Twelve provinces and territories, plus work outside Canada

    • Alberta
    • British Columbia
    • Manitoba
    • New Brunswick
    • Newfoundland and Labrador
    • Nova Scotia
    • Northwest Territories
    • Nunavut
    • Ontario
    • Prince Edward Island
    • Quebec
    • Saskatchewan
    • Yukon
    • Outside Canada

    All calculators and situations

  • Docs
  • Pricing
  • Conformance
Get API keys

Legal

  • Privacy
  • Terms
  • API terms
  • Cookies
  • Security
  • Accessibility

Legal · Last updated 30 October 2026

API Terms and Acceptable Use

Draft for legal review. This text was checked against Takehome's code on 30 October 2026; a lawyer has not reviewed it yet.

In short

  • Free during early access. Every account is on the Developer plan: 100,000 live calculations per calendar month (UTC) at $0. Test keys are unmetered. No card is taken and nothing converts to a paid plan without your separate agreement and at least 30 days' notice.
  • Hard stop, no surprise bills. At the quota the API refuses live calls with HTTP 402 plan_limit. If the usage meter is unavailable, the API refuses the call (HTTP 503 store) rather than serving it unmetered.
  • Your keys are your responsibility. We show each key once and keep only a hash. Use keys only from your servers.
  • We do not keep your request data. Calculation inputs are processed in memory to return a result and are not stored or logged by our code.
  • No service level. Early access has no uptime commitment. We may change or stop the service; we will give 30 days' notice of a shutdown or of a breaking change to /v1 except for urgent security or legal reasons.
  • Results are estimates. You remain responsible for your payroll. The Terms of Use (disclaimers, liability, governing law) also apply.

1. Agreement

These API Terms apply to your use of the Takehome API at https://takehome.gautamkhosla.com/v1/ and to API keys issued to you. The API is run by Gautam Khosla, an individual in Ottawa, Ontario, Canada ("we", "us"). Contact: developwith.gt@gmail.com.

These API Terms add to the Terms of Use; if they conflict on an API matter, these API Terms govern. The Privacy Policy explains how we handle personal information. At signup you confirm, with a checkbox on the form (or "accept_terms": true on POST /v1/signup), that you agree to the Terms of Use and these API Terms and have read the Privacy Policy; when you press the button on the verification page we record the time and the version you accepted. By using the API you agree to these terms. If you use the API for an organization, you confirm you are authorized to accept these terms for it, and "you" includes that organization.

2. Eligibility and accounts

  • The API is for developers and businesses. You must be at least the age of majority where you live.
  • One account per email address. You sign up with an email address, verify it through a link valid for 24 hours, and then receive one test key and one live key.
  • Do not create multiple accounts to get more free quota, and do not sign up using an email address you do not control.
  • Keep your email address current. We send account, security and service notices to it.

3. API keys

  • Keys look like np_test_ or np_live_ followed by 32 hexadecimal characters. Send them as Authorization: Bearer <key>.
  • We show each key once. We store only a SHA-256 hash and cannot recover or resend a key.
  • Keep keys secret and server-side. The keyed API routes do not accept cross-origin browser requests, so do not put keys in web pages or mobile apps. Do not commit keys to source control or share them.
  • You are responsible for all use of your keys until you revoke or rotate them.
  • You can rotate a key with POST /v1/keys/rotate (the previous key of that kind stops working at once) or revoke one with POST /v1/keys/revoke. The test key can rotate or revoke only the test key; the live key can do both. GET /v1/keys lists the kinds and prefixes of your active keys.
  • Revoking needs { "kind": "test" } or { "kind": "live" } exactly; any other body is refused with HTTP 400 and revokes nothing.
  • If you lose or revoke the live key, you cannot issue a new live key yourself (the test key cannot), and if you lose both keys you cannot issue new ones. Email us from your account address and we will help.
  • Tell us promptly at developwith.gt@gmail.com if you believe a key has been compromised, and rotate it.

4. Early access, plans and pricing

  • Now: every account is on the Developer plan at $0 CAD, with 100,000 live calculations per calendar month (UTC). Test keys (np_test_) run the same engine, return the same results for the same inputs, and are not metered.
  • Published paid tiers (Starter $49 CAD for 25,000, Growth $149 CAD for 150,000, Business $399 CAD for 1,000,000 live calculations a month) are listed on the pricing page for planning only. They are not offered and not an offer to sell. Checkout is turned off: POST /v1/billing/checkout returns 501 billing_unavailable.
  • Before any charge: if we introduce paid plans, we will publish the prices and terms, give at least 30 days' notice by email, and charge only if you separately choose a paid plan and provide payment details. We will not move you to a paid plan automatically. Prices will be in Canadian dollars; applicable sales taxes would be added if we are required to collect them.
  • We may change the free quota for future months. We will give at least 30 days' notice of a reduction.

5. How usage is counted

Only live keys are metered. The meter resets at 00:00 UTC on the first day of each month. Successful responses include X-Usage-Limit, X-Usage-Remaining and X-Usage-Reset.

Call What counts
POST /v1/deductions 1 calculation when the response is a successful result. A request that fails validation or is refused by the engine (including Quebec, jurisdiction_not_supported) is not counted
POST /v1/deductions/batch Every item in the requests array (1 to 25), including items that return an error inside an otherwise successful batch
POST /v1/deductions/year The number of pay periods in the year you request (for example, 26 for biweekly), when the projection succeeds
Any call that would take you past your quota Refused whole with HTTP 402 plan_limit. Nothing is counted

If as_of is missing, the API uses the current date in UTC to choose the rules; on a year projection a missing as_of means 1 January of the current UTC year.

6. Technical limits

These limits are in force today. We may change them; we will try to give notice of any reduction.

  • Per IP address, at Cloudflare. Every API path (/v1/..., /health and /openapi.json) takes at most 10 requests per 10 seconds from one IP address, counted by a Cloudflare rate limiting rule before our code runs, whatever the key or route. Above it, Cloudflare answers HTTP 429 with its own page for 10 seconds: not JSON and not our error format, so error.code is absent; wait 10 seconds and retry. So one IP address gets at most 60 API requests a minute in all; every per-minute limit below applies within that. A pay run of 1,000 employees is 40 batch calls, about 40 seconds from one IP address. The rule counts by IP address alone: test-key and live-key calls from one address share it, so test traffic sent from the address your live calls use can make them wait, and every caller behind one shared outbound address (an office network, a CI service, or a serverless platform such as Cloudflare Workers, whose outbound requests may share addresses with other customers) shares it too. Code that runs on Cloudflare Workers can run the engine itself, with no API call, from the takehome-ca WASM package (in the source repository, not yet published on npm).
  • Request bodies: at most 16 KiB (48 KiB for a batch, 8 KiB for signup and email verification), and JSON nested at most 16 levels deep (HTTP 413 payload_too_large above the size).
  • Batches: 1 to 25 calculations per call (HTTP 400 batch_too_large above 25; nothing is calculated or counted).
  • Year projections: at most 27 pay periods (pay_period 1, 2, 4, 10, 12, 13, 22, 24, 26 or 27). A weekly, daily or hourly year (52, 53, 240 or 2000) is HTTP 400 year_too_large and nothing is calculated or counted; send those pay periods as batches.
  • Requests from one IP address to the signup route: 5 per 60 seconds (an IPv6 address counts by its /64 network). To the email verification route: 10 per 60 seconds. To public listing routes (/v1/rules, /v1/jurisdictions, /v1/conformance, /v1/changes, /openapi.json, /health): 120 per 60 seconds, so from one IP address the Cloudflare rule above (60 a minute) is the one you meet. These limits are counted on each server instance separately, so they are approximate. Exceeding one of ours returns HTTP 429 rate_limited in our JSON error format; back off and retry.
  • Verification emails, counted in our database over any 24 hours: at most one every 10 minutes and 3 in total to one address (letter case and a +tag do not matter), and at most 30 for signups from one network (one IPv4 address or one IPv6 /48; then HTTP 429 rate_limited). An email our provider refuses (it answers with an error, so nothing was sent) still counts toward the network's 30, not toward the address's own limits, and no account is kept for it. Signup needs the Cloudflare Turnstile token from the form at /signup/, so accounts are opened from a browser; a signup without a valid token gets HTTP 403.
  • Account deletion (DELETE /v1/account): about 5 refused attempts per 60 seconds per IP address (a missing or wrong key, a test key, or a confirmation that does not match; then HTTP 429). A deletion with the live key and the matching email is never refused by our own limits or budgets; the Cloudflare rule above still applies.
  • Requests with an account's test keys and with its live keys are limited separately: 120 per 60 seconds each, counted on each server instance separately, so approximate (HTTP 429 rate_limited). From one IP address the Cloudflare rule above allows 60 a minute for both together, so these 120 are reached only from more than one address. Test keys may also run at most 5,000 calculations a minute per account with its test keys (one per single calculation, the item count of a batch, the pay periods of a year projection; HTTP 429 rate_limited; a request answered with an error counts nothing, and a batch answered with HTTP 200 counts all its items, including items that failed). Key rotations: at most 10 a UTC day (00:00 to 24:00 UTC) made with the test key and, separately, 10 made with the live key, so a test key can never use up the live key's rotations (HTTP 429). Revoking a key is never refused by our own limits or budgets; the Cloudflare rule above still applies.
  • Live calls: at most 3,600 a day (UTC) per account with its live key, counting each request once (a batch or a year projection is one call), which still allows the whole monthly quota one call at a time. Above it: HTTP 429 rate_limited, nothing is counted, and it resets at 00:00 UTC. Test-key calls do not count toward it.
  • Webhooks: at most 5 endpoints per account (20 on a paid plan; HTTP 409 for one more, which does not count as a registration unless it raced another registration of the same account that was stored first; a dispatch delivers to at most 5 endpoints, so an account with more gets HTTP 409 and nothing is sent); at most 20 endpoint registrations per account a UTC day (deleting an endpoint is never refused by our own limits or budgets; the Cloudflare rule above still applies); and at most 100 deliveries per account in a UTC clock hour (for example 14:00 to 15:00 UTC) and 300 a UTC day, counting one per endpoint for each dispatch and one per replay (HTTP 429 rate_limited; a dispatch that would pass either limit is refused whole and sends nothing). The delivery log is listed 20 records at a time (GET /v1/webhooks/deliveries, with a cursor for the next page). These counts are kept per account in our database, so deleting endpoints or rotating keys does not reset them. Delivery records are kept 30 days, and at most the newest 100 per endpoint (each new record deletes the oldest beyond that).
  • The per-minute limits above (requests per IP address and per key kind, refused account deletions, and test-key calculations) are counted on each server instance separately, so they are approximate, and the per-IP ones use the IP address Cloudflare reports in the CF-Connecting-IP header. The daily and hourly limits (verification emails, key rotations, live calls, webhook registrations and deliveries) are kept in our database.
  • Money amounts in a calculation: zero or more, at most 15 digits before the decimal point and at most 2 decimal places (HTTP 400 invalid_request naming the field). In a year projection, gross_pay, pensionable_earnings, insurable_earnings, taxable_benefits and additional_tax_requested times the number of pay periods must also stay within 15 digits.
  • Whole numbers in a calculation: pay_period is one of 1, 2, 4, 10, 12, 13, 22, 24, 26, 27, 52, 53, 240 or 2000; cpp_months is 0 to 12; pay_periods_elapsed is 0 to pay_period; dependants_under_19 and dependants_disabled are 0 to 99 (HTTP 400 invalid_request naming the field).
  • An unknown field in a request body is rejected on every route, by name (HTTP 400 unknown_field). The batch body takes only requests: a value meant for every item (a claim code, as_of) goes on each item, never next to requests. The documented fields 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) are refused by name too (HTTP 400 invalid_request).
  • Claim codes are 0 to 10 or E (or e); codes 2 to 10 use the amounts the CRA prints in the claim-code table of the edition as_of selects.
  • A year projection (POST /v1/deductions/year) checks its body exactly like POST /v1/deductions, then applies each field it accepts to every pay period and refuses, by name and with the reason, each documented field it cannot apply (year-to-date totals, bonus and retroactive pay, commission, Quebec and change-of-province fields, date_of_birth, cpp_election_after_65, Option 2). Every pay date falls in one calendar year, and it runs at most 27 pay periods (above, Year projections).

7. Availability, outages and discontinuation

  • The API is in early access and is provided without any service level agreement, uptime commitment, support response time or service credits.
  • Fail closed. If the database cannot be read, every call with a key returns HTTP 503 store and no result (the key itself is looked up there), and so do signup and verification. If it can be read but not written, live calculation calls and every request that has to store something (a signup that sends an email, verification, key rotation and revocation, account deletion, and webhook registration, deletion, dispatch and replay) return HTTP 503 store, while calls that only read (test calculations, and listing keys, endpoints and deliveries) keep working. If the database fails after a live calculation, the result is discarded. Build retries into your integration.
  • Shared daily limits. The hosted API runs on Cloudflare's free plan, whose daily limits are shared by every user, and with our other services on the same Cloudflare account: a number of requests a day, and a number of database rows read and written a day. Requests from two or more IP addresses, or a small number of accounts each used up to its own daily limits, can use them up; until they reset at 00:00 UTC, the API (signup and every keyed route) can then be unavailable for everyone. The website and its calculators keep working.
  • We may suspend the API for maintenance or emergencies without notice.
  • Discontinuation. We have publicly committed to a test of whether the hosted service should continue, and we may stop the hosted API. If we do, we will give at least 30 days' notice by email, except where we must stop sooner for security or legal reasons. The engine, rule data and API source code remain published under the Apache License 2.0, so you can run your own copy.

8. Data in your requests

  • What we do with it. We process each request only to compute and return its result. Cloudflare runs our code in the data centre that receives your request, which may be outside Canada. Request bodies are held in memory for the duration of the request and are not written to our database. Our code does not log request bodies, and our logger refuses to log objects containing salary fields.
  • What is recorded. For each live call we increase your monthly usage count. Cloudflare keeps request metadata (address, method, status, timing, headers with authorization values masked, and connection data including the caller's IP address) for up to 7 days. See the Privacy Policy.
  • What we never do. We do not sell request data, use it for advertising, or use it to train models. We cannot use it later, because we do not keep it.
  • Your responsibilities. Send only what a calculation needs. The API does not accept names, Social Insurance Numbers, addresses or other direct identifiers, and you must not try to embed them in accepted fields. If you send information about your employees or clients, you are responsible for having the authority to do so and for any notice or consent the law requires. For that information we act as your service provider.

9. Webhooks

  • You can register HTTPS endpoints with POST /v1/webhooks. Registering, deleting, dispatching and replaying need the live key; the test key can only list endpoints and deliveries. We check that the address is public and not a private or internal network address, and not on gautamkhosla.com (where this service runs), at registration and again before each delivery. Redirects are not followed.
  • The whole endpoint address is shown once, in the answer to its registration. After that, listing or reading an endpoint, with either key, shows only its scheme and host (https://<host>/), because receivers often keep a credential in the path or query.
  • An endpoint address may be at most 2,048 bytes long and may not contain a user name or password (HTTP 400), and one account's endpoint addresses together may be at most 16,384 bytes (HTTP 409). A refused registration stores nothing and does not count toward the registration limit, unless it raced another registration of the same account that was stored first.
  • The signing secret is shown once when you register. We store it in readable form because we need it to sign deliveries. Delete and re-register the endpoint to change it.
  • Deliveries are sent only when you call POST /v1/webhooks/dispatch (with from and to rule-set versions) or replay a delivery. We do not currently send webhooks automatically when rules change.
  • Each delivery is tried up to 3 times, each attempt with a 5-second timeout; a dispatch sends to its endpoints in rounds, and the next round starts at least 1 second, then at least 2 seconds, after the previous round's slowest attempt ends. Your server's response body is read up to 4 KiB and discarded.
  • An account runs one dispatch or replay at a time: while one is running, another gets HTTP 409 and sends nothing (retry when the first has answered; at most 60 seconds).
  • Right before each attempt we check that the endpoint still exists, so once you delete an endpoint it gets no further attempt, except one whose check ran in the moment before your deletion was stored, which can arrive a moment after the deletion answered (at most one per endpoint, since only one dispatch or replay of an account runs at a time, unless our database takes more than 20 seconds to answer that check).
  • Each delivery carries a takehome-signature: t=<unix time>,v1=<hex> header, an HMAC-SHA256 over the timestamp and body. Reject any signature whose timestamp is more than 300 seconds from your clock.
  • We keep an endpoint until you delete it. Delivery records are kept 30 days and at most the newest 100 per endpoint, and deleting an endpoint deletes its delivery records.

10. Results and your responsibility

  • Every response names the rule_set_version and engine_build_sha256 that produced it, and may carry warnings such as RULE_SET_PROPOSED (2027 preview rules: do not file from these numbers) or PRORATED_RECONCILIATION. Show or act on warnings in your product.
  • The accuracy statement in section 4 of the Terms of Use applies to API results.
  • You are responsible for the deductions you withhold, remit and report, for checking results against the CRA's Payroll Deductions Online Calculator or publications before relying on them, and for how your product presents them to your users.
  • Do not present results as issued or endorsed by the Canada Revenue Agency.

11. Acceptable use

Do not:

  • share keys, resell access to our hosted API as a standalone service, or let others use your keys;
  • create accounts or keys to get around quotas or limits, or use test keys to run production payroll so that live calls go unmetered;
  • send traffic designed to degrade the service, or load test without our written permission;
  • probe or test security except under our Security and Responsible Disclosure page;
  • sign up with, or cause verification emails to be sent to, addresses you do not control;
  • register webhook endpoints you are not authorized to receive traffic on;
  • use the API for anything unlawful, or in a way that infringes others' rights.

The source code is open: if you need more than the hosted service allows, you may run your own copy under the Apache License 2.0.

12. Suspension and termination

  • We may suspend or revoke keys, or close an account, if you breach these terms, if your use creates a security risk or harms the service or others, or if the law requires it. Where practical, we will tell you first and give you a chance to fix the problem.
  • You may stop using the API at any time and delete your account with DELETE /v1/account (your live key, and your account email in the body as confirmation), or ask us to delete it (Privacy Policy, section 10).
  • Sections 3 (your responsibility for key use before revocation), 10, 14 and 16 survive termination.

13. Changes to the API and these terms

  • The API is versioned under /v1. We may add fields, endpoints and warnings without notice; build clients that ignore unknown response fields.
  • We will give at least 30 days' notice by email before a change that breaks existing /v1 integrations, unless an urgent security or legal reason requires a faster change.
  • We may update these API Terms. We will email account holders at least 30 days before a change that materially reduces your rights or adds charges. Continuing to use the API after the effective date means you accept the change; if you do not accept it, stop using the API and ask us to delete your account.

14. Disclaimers, liability and indemnity

  • No warranty. To the extent the law allows, the API and all results are provided "as is" and "as available", without warranties or conditions of any kind.
  • Limitation of liability. To the extent the law allows, we are not liable for indirect, incidental, special, consequential or punitive loss, lost profits or revenue, lost data, or any tax, penalty, interest or assessment arising from use of the API. Our total liability for all claims relating to the API is limited to the greater of the fees you paid us for the API in the 12 months before the claim (currently $0) and CAD $100. These limits do not apply to fraud, intentional misconduct, or liability that cannot be limited under applicable law.
  • Indemnity. If you use the API for a business, you will indemnify us against third-party claims, and related reasonable costs, arising from your breach of these terms or from your product's use of the API, except to the extent caused by our own breach or misconduct.

15. Feedback

If you send suggestions, you allow us to use them without obligation to you.

16. Notices and general terms

  • We send notices to your account email address. Send notices to developwith.gt@gmail.com.
  • Governing law, courts, consumer rights, severability and the other general terms in sections 12, 13 and 15 of the Terms of Use apply to these API Terms.
  • You may not transfer your account without our consent. We may transfer the service and these terms to a successor who agrees to be bound by them, and we will tell you if we do.

Source: legal/api-terms.md in the Takehome repository, rendered as written. Questions: developwith.gt@gmail.com.

Takehome

Every deduction, with its receipt.

Takehome is a calculation of CRA T4127 formulas. It is not a payroll provider and does not file returns. The CRA Payroll Deductions Online Calculator is the authoritative source.

Set in subsets of Source Serif 4 by Adobe and IBM Plex Sans and Mono by IBM, under the SIL Open Font License (Source Serif licence, Plex licence).

Calculate

  • Calculators
  • Rates
  • Embed
  • CPP 2027

Build

  • Docs
  • API reference
  • Pricing
  • Get API keys
  • Changes
  • RSS

Proof

  • Conformance
  • Findings
  • How deductions work
  • T4127
  • Sitemap

Legal

  • Privacy
  • Terms
  • API terms
  • Cookies
  • Security
  • Accessibility

PDOC forms matched: 8,905 / 9,002 default8,987 / 9,002 with rounding_compat: pdoc15 unexplained, all listedLatest PDOC capture 2026-09-15