In short
- The calculators run in your browser. The pay figures you type into a Takehome calculator are computed on your device and are not sent to us.
- If you sign up for API keys, we store your email address, a one-way hash of each API key, a count of your live calculations per month, and any webhook endpoints you register. We keep these until you delete your account, which you can do yourself through the API or by emailing us. An address that is never verified is deleted automatically once it is 30 days old, unless a new verification link was requested in the last 24 hours. Each time a verification email is sent we also store the network address the request came from (your IPv4 address, or the first 48 bits of an IPv6 address) and a one-way hash of your address, with the time, to limit abuse; it counts for 24 hours and is deleted by the hourly cleanup within the next 24 hours, so it is kept for at most 48 hours (longer only if every hourly cleanup of a whole day fails, which takes a database outage or our database's daily write limit used up again within 17 minutes of each daily reset at 00:00 UTC; then until the first run that succeeds), also after the account is deleted, so the email limits still apply.
- API calculation requests are processed in memory to return a result. We do not store them and our code does not log them.
- IP addresses are seen by our host, Cloudflare, and appear in short-lived logs (kept 7 days at most), in security alerts, and, for signups, in the send records described above.
- The signup form uses Cloudflare Turnstile to check that you are a person. It loads only when you start filling in the form, and Cloudflare processes your IP address and signals from your browser and device to tell people from bots, and also uses those signals to improve Turnstile, for which it decides itself how they are used. See section 4 and Cloudflare's Turnstile privacy addendum.
- Our providers are Cloudflare (hosting, database, logs, the Turnstile check), Resend (sending email), Google (our Gmail inbox) and GitHub (security reports). They process information in the United States.
- No cookies, analytics or ads in our code. We do not sell or rent personal information.
- Questions or requests: Gautam Khosla, developwith.gt@gmail.com. You can also complain to the Office of the Privacy Commissioner of Canada.
1. Who we are and who is accountable
Takehome, at takehome.gautamkhosla.com, is run by one person: Gautam Khosla, an individual in Ottawa, Ontario, Canada. Takehome is not a company. In this policy, "we", "us" and "our" mean Gautam Khosla.
Gautam Khosla is the person accountable for Takehome's handling of personal information under the federal Personal Information Protection and Electronic Documents Act (PIPEDA), and the person in charge of the protection of personal information for Quebec purposes (section 12).
Privacy contact: Gautam Khosla, developwith.gt@gmail.com. We do not publish a street address. Requests by email are accepted for every right in this policy. If you need to send something by post, email us and we will give you a postal address.
2. What this policy covers
This policy covers:
- the website at takehome.gautamkhosla.com, including the calculators, documentation, pricing and signup pages;
-
the embeddable widget (
/embed.js) when another website loads it; -
the Takehome API at
https://takehome.gautamkhosla.com/v1/; - the emails we send; and
- a staging copy at takehome-staging.gautamkhosla.com, which we use for testing. Signup there is closed to the public: it sends email only to addresses we list for our own testing, and refuses every other address before anything is stored or sent. It has its own separate database and uses the same providers. Because it holds only our own test addresses, it has no hourly cleanup: we clean its database by hand, with the same deletions, after each test session.
It does not cover the public source code repository on GitHub (GitHub's own terms and privacy statement apply), Canada Revenue Agency (CRA) websites we link to, or websites that embed our widget (their own policies apply).
3. What we do not collect
- Calculator inputs. Gross pay, pay date, pay frequency, claim codes, bonuses, year-to-date amounts and every other figure you type into a calculator are computed by a WebAssembly engine inside your browser. The calculator form has no submit action, the page makes no network request when it recalculates, and our Content Security Policy only lets pages connect to our own domain. We never receive these figures.
-
Identity details. We do not ask for your name, Social Insurance Number, address, phone number or payment details. The API rejects any field in a request body that it does not recognise, on every route, and none of the fields it accepts is a name, SIN, address, account number or date of birth: a
date_of_birthsent with a value is refused, as the API Terms say. The fields it accepts are pay amounts and payroll settings, such as claim codes, a CPP exemption and a count of dependants. - Tracking. Our code sets no cookies and does not use local storage, session storage or IndexedDB. We run no analytics, advertising, tracking pixels or fingerprinting. Our Content Security Policy only allows scripts from our own domain, plus Cloudflare Turnstile's script from challenges.cloudflare.com, which the signup page loads when you start filling in the form; so Cloudflare features that try to add scripts to our pages (its Web Analytics beacon and bot-detection script) are blocked by your browser and do not run. See our Cookies and Local Storage Notice.
- Payment information. Paid plans are not offered and no payment processor is connected. We will update this policy before collecting any payment information.
We do not sell, rent or trade personal information, and we do not share it for advertising.
4. What we collect, why, and for how long
| Information | When we get it | Why | Where it is kept | How long |
|---|---|---|---|---|
| Email address | When you submit the signup form. We store it in lower case, before you verify it | To send your verification link; to identify your account; to contact you about your account, security, service changes and changes to our terms or this policy | Our database (Cloudflare D1) | Until you delete your account (section 10). An address that is never verified is deleted by a daily cleanup once it is 30 days old, unless a new verification link was requested in the last 24 hours. If our email provider reports that the verification email could not be sent, the address is deleted at once, unless the account already has keys or another link |
| Account record: a random account ID, whether your email is verified, your plan name, an unused billing field (always empty), the time the account was created (for accounts created before this change was released, the time it was released), and the time you accepted the Terms and Privacy Policy with the version you accepted, plus a history of each acceptance | Signup and verification. Your acceptance is recorded only when you press the button on the verification page | To run your account, apply your plan's limit and keep a record of your acceptance | Cloudflare D1 | Until deletion |
| Email verification token | Created at signup and placed in the link we email you | To confirm you control the address | Cloudflare D1 stores a SHA-256 hash of the link, an expiry time 24 hours after issue, the time and version of the Terms you accepted on the signup form, and your address in a normalised form (lower case and without a +tag, and for Gmail addresses also without dots) so the resend limits apply to one inbox however the address is written. Separately, for each verification email sent we keep a send record: its time, the network it was requested from (the IPv4 address, or the first 48 bits of an IPv6 address, its /48 network), a random id for that send, and a SHA-256 hash of your normalised address (not the address itself), with no account, to enforce the per-address and per-network limits. Because it is not linked to an account, the send record stays when you use the link or delete your account, so those limits still count it | Deleted when the link is used, and immediately if our email provider reports that the email could not be sent. If the provider did not reply, the link is kept until it expires, because the email may have arrived, and it keeps counting toward the resend limits; signup then tells you we could not confirm the email was sent and to try again in 10 minutes if it does not arrive. An unused link is deleted by the hourly cleanup after it expires. A send record counts for 24 hours and is deleted by the hourly cleanup within the next 24 hours (so it is kept for at most 48 hours, also after the link is used or the account is deleted; longer only if every hourly cleanup of a whole day fails, as described in the summary above, and then until the first run that succeeds); if our email provider reports that the email could not be sent, the record's address hash is removed at once, so it still counts toward the per-network limit for 24 hours but toward no per-address limit. If the provider did not reply, the send record is kept whole and counts toward both |
| API keys (one test key, one live key) | When you verify | To authenticate your API calls | We show each key once and store only its SHA-256 hash, its kind (test or live), its prefix and whether it is revoked | Until deletion. Revoked keys stay as revoked records |
| Usage count | Each live calculation counted under the API Terms (section 5) | To enforce your monthly quota and the daily limit of live calls, and fill the X-Usage-* response headers |
Cloudflare D1, one row per account per calendar month (UTC): the number of calculations, and the UTC date of your last live call that month with the number of live calls made that day | Until deletion. Test-key calls are not counted |
| API calculation requests (pay amounts and the other fields you send) | Each API call | To calculate and return the result | Memory of the Cloudflare server that handles the request, for the duration of the request | Not stored. Not written to our database. Our code does not log request bodies |
| Webhook endpoints (the URL you register, at most 2,048 bytes and 16,384 bytes for all of an account's URLs; a signing secret; the time created) | When you register a webhook | To sign and send rule-change notifications you ask us to dispatch | Cloudflare D1. The signing secret is stored in readable form because we need it to sign each delivery | Until you delete the endpoint |
| Webhook delivery records (event name, the rule-set change content we sent, status, number of attempts made, last error message cut to 200 characters, last HTTP status, timestamps) | Each dispatch or replay you request | So you can see and replay deliveries | Cloudflare D1 | Deleted automatically when you delete the endpoint, and by the daily cleanup once they are 30 days old. At most the newest 100 per endpoint are kept: each new record deletes the oldest beyond that |
| Usage limit records | Each key rotation, webhook endpoint registration and webhook delivery | To enforce the per-account limits in the API Terms, so deleting or rotating something does not reset them | Cloudflare D1: one counter per account and kind of action: your account ID, the kind of action, the UTC day and clock hour it counts and how many actions were made that day and that hour (no IP address, key or endpoint address). Records in the earlier format (one per action, with its time) may still exist from before this change | A counter is rewritten by the next action of its kind, deleted by the daily cleanup once the UTC day after its day is over (it then counts nothing), and deleted with your account, also when one of your actions lands at the same moment as the deletion (a counter is written only while the account exists). Earlier-format records are deleted by the daily cleanup once 24 hours old, and with your account |
| IP address and request details for API traffic | Every request to an address starting with /v1, and to /health and /openapi.json (the only requests that run our code) |
To keep the service running and to investigate errors and abuse | Cloudflare's Workers Logs. Cloudflare records the request (web address, method, headers), the response status and Cloudflare connection data, which includes your IP address and an approximate location derived from it. Cloudflare masks header values whose names contain "auth", "key", "secret", "token" or "jwt", and cookies | 7 days at most (3 days on Cloudflare's free plan), then deleted by Cloudflare |
| IP address in security events | When one IP address (an IPv6 address counts by its /64 network) fails authentication 5 times within 60 seconds, when a request is refused because a monthly quota is used up, when the server returns an error, when an account deletion is refused because the confirmation does not match, or when an account is deleted. (A failed webhook delivery, a failed cleanup, 80 or more verification emails in 24 hours (signup_mail_volume), a signup or rate limit set to a malformed value (signup_config_invalid, rate_limit_config_invalid), the Turnstile check being unavailable on our side or Cloudflare's (turnstile_unavailable) or our database failing to answer (store_unavailable) is also logged and alerted, with no IP address. A failed Turnstile check is logged as turnstile_rejected, with no IP address and no alert) |
To detect key guessing, abuse and outages | A log line with the event type, HTTP status, path and IP address, in Workers Logs. Except for a completed deletion, the same details are emailed to Gautam Khosla as an alert, at most one email per kind of event an hour and one a day for the whole service (four a day for a database failure), so at most 16 a day, counted in our database; each server instance also keeps its own limits (one per kind an hour and 12 a day, of which the events requests and signups can cause use at most 6, and 4 a day are kept for a database or cleanup failure). The rest are only logged. While our database cannot answer, no request sends an alert email: only the hourly cleanup emails that it failed, at most once an hour (24 a day). The staging copy (section 2) counts its own alerts separately, with the same limits | Logs: 7 days at most. Alert emails: Resend keeps them 30 days; in our inbox, until we delete them (there is no automatic deletion yet) |
| IP address in Cloudflare's rate limiting | When more than 10 requests to the API (addresses starting with /v1, and /health and /openapi.json) come from one IP address within 10 seconds, and Cloudflare blocks the rest for 10 seconds |
To stop floods of requests before our code runs | Cloudflare's security event records for our domain (Security Events in the Cloudflare dashboard): the IP address, the request's address and method, the time, the country Cloudflare derives from the IP address, and the rule that blocked it | Kept by Cloudflare for its own period; we have not verified how long on the free plan. We do not copy them |
| IP address for rate limiting | Signup, verification, account deletion and public listing requests (the address Cloudflare reports in the CF-Connecting-IP header) | To limit requests per IP address (an IPv6 address counts by its /64 network, and an IPv4 address written in IPv6 form counts as that IPv4 address) | Server memory. The one exception is the network of each verification email sent (IPv4 address or IPv6 /48), kept with its send time in Cloudflare D1, as described under Email verification token | Memory: discarded when that server instance restarts. Send records: count for 24 hours, deleted by the hourly cleanup within the next 24 hours (at most 48 hours, as described under Email verification token), and their address hash at once if the email could not be sent |
| Cloudflare Turnstile check | When you start filling in the signup form (the script is not loaded before that) | To tell people from bots, so the form cannot be used to flood inboxes or create accounts in bulk | Cloudflare runs the check in a frame from challenges.cloudflare.com and processes your IP address and signals from your browser and device, as described in Cloudflare's Turnstile privacy addendum. Our server receives a one-time token from the form and sends it, with your IP address, to Cloudflare, which answers whether the check passed, for which hostname and form; we do not store the token or the answer. Cloudflare also processes these signals to improve Turnstile; for that purpose it is not our provider but decides for itself (its addendum: "Cloudflare is a data controller of Signals that we process to improve Turnstile's bot detection") | Not kept by us. Cloudflare's own retention is in its addendum |
| Emails you send us | When you write to developwith.gt@gmail.com or reply to one of our emails | To answer you and keep a record of what was asked and decided | Our Gmail inbox | As long as needed to deal with your request, normally no more than 2 years after it is closed, except records the law requires us to keep longer (section 11) |
| Security reports | When you report through GitHub private vulnerability reporting | To fix the issue and credit you if you want | GitHub | For the life of the advisory record |
Website pages and files. Pages, scripts, fonts and the calculation engine are served by Cloudflare as static files without running our code, so those requests do not create our Workers Logs. The same goes for an address that is not a page or file: Cloudflare answers it with the site's 404 page, without our code. Cloudflare processes them on its network, including your IP address and browser details, and shows us only aggregate traffic statistics.
We use personal information only for the purposes listed above. If we want to use it for a new purpose, we will tell you first and, where the law requires, ask for your consent.
5. Service providers and processing outside Canada
We use these providers. Each processes information on our behalf to provide its service to us.
| Provider | What it does for Takehome | Location |
|---|---|---|
| Cloudflare, Inc. (San Francisco, United States) | Hosts the website, runs the API code, stores the database, keeps request logs, filters attacks and bots, and runs the Turnstile check on the signup form | Cloudflare runs the API code in the data centre that receives your request, usually one near you, which may be outside Canada. Cloudflare does not offer a Canadian location for this database service, so assume your account data is stored outside Canada, in the United States or another country where Cloudflare operates. Cloudflare says it primarily stores information in the United States and the European Economic Area |
| Resend (operated by Plus Five Five, Inc., United States) | Sends verification and alert emails. It receives your email address and the message, including your one-time verification link | United States. Resend keeps email data for 30 days |
| Google LLC (Gmail) | Hosts our inbox, developwith.gt@gmail.com, which receives your emails and our alert emails | Google's data centres, including in the United States |
| GitHub, Inc. (United States) | Hosts our public source code and receives security reports | United States |
Your information may be processed in the United States and other countries, and while it is there it may be accessible to the courts, law enforcement and national security authorities of those countries. We rely on each provider's contractual commitments to protect it.
Cloudflare also asks your browser to report network errors to Cloudflare (Network Error Logging). These reports contain the page address, the type of error and timing. Cloudflare states that it uses the IP address of a report only to work out the network, country and city area, and does not log it.
We do not disclose personal information to anyone else except where the law requires it (for example, a valid court order), to protect the security of the service, or with your consent.
6. Consent and your choices
- You can use every calculator without giving us any personal information.
- By submitting the signup form you consent to the collection and use of your email address and account information described in section 4. The form asks you to tick a box confirming that you agree to the Terms and API Terms and have read this policy; when you press the button on the verification page we record when you ticked the box and which version it was, and keep each acceptance as a history. Opening the link alone does nothing. API keys are only issued after you verify the address.
- If someone else entered your email address, you can ignore our email. No keys are issued unless someone opens the link and presses the button. If the address already has keys, we send a short notice instead of a link, and nothing changes (if every key of that account was revoked, the notice says so and how to start again); signup gives the same answer whether or not an address has an account. We send at most one email every 10 minutes and three in 24 hours to one address (letter case and a +tag do not matter, and Gmail addresses that differ only by dots count as one), and at most 30 in 24 hours for signups from one network (one IPv4 address, or one IPv6 /48), after which signup answers that there were too many signups from your network in the last 24 hours. If 80 or more verification emails are attempted across all addresses in 24 hours (counting emails our provider refused), we are alerted; signup keeps working. An email our provider refuses counts toward the limit of 30 for your network only, never toward your address's own limits, and the address is not kept; an email whose sending we could not confirm counts toward all of them. The unverified address is deleted automatically once it is 30 days old, unless a new verification link was requested in the last 24 hours; email us to delete it sooner.
- You can withdraw consent at any time by deleting your account (section 10). Without an account you cannot use the hosted API. Withdrawal does not affect records we must keep by law.
- We do not send marketing email. We will not send any without first getting your express consent.
7. Retention and deletion
- Account information (email, account record, key hashes, usage counts, webhook endpoints and delivery records) is kept until you delete the account yourself or ask us to (section 10). Webhook endpoints can also be deleted one by one.
- An hourly cleanup deletes expired verification tokens and send records older than 24 hours. Once a day (at the first hourly run of the UTC day that succeeds) it also deletes accounts that were never verified within 30 days of signup, hold no keys and have no unexpired verification link, and delivery records older than 30 days.
- When we delete an account, we remove its rows from our database. The database keeps automatic restore points for up to 30 days, so deleted data disappears from those restore points within 30 days.
- Cloudflare request logs are deleted after 7 days at most. Resend deletes email data after 30 days.
- Calculation inputs are never kept.
- If you ask for access to your information, we keep it until the request and any complaint about it are fully dealt with.
8. How we protect information
These are the safeguards that exist in Takehome's code and configuration today:
- Plain HTTP requests are redirected to HTTPS. Website pages send HTTP Strict Transport Security for one year, including subdomains.
- Website pages send a strict Content Security Policy: scripts, styles, connections and images are limited to our own domain, and other sites may not frame our pages.
- API keys are 128 bits of cryptographically secure randomness. We store only a SHA-256 hash, compare in constant time, and cannot recover a lost key.
- Verification tokens are 128 bits of randomness, stored only as a hash, valid for 24 hours and usable once.
- You can rotate or revoke your keys through the API at any time.
- Calculation request bodies are limited to 16 KiB (48 KiB for a batch) and are never written to the database. Our logging code refuses to log any object containing a salary field, and removes API keys and webhook secrets from log text.
- API routes that take a key do not allow cross-origin browser requests, so a key cannot be used from another website's page.
- Webhook URLs must use HTTPS and are checked before registration and again before each delivery, so they cannot be pointed at private or internal network addresses. Redirects are not followed.
- If the usage database cannot be reached, the API refuses the calculation instead of serving it unmetered.
- Provider credentials are kept as encrypted Cloudflare secrets, not in our source code. Only Gautam Khosla has access to the Cloudflare and Resend accounts and the inbox.
Limits you should know about: webhook signing secrets are stored in readable form (we need them to sign deliveries); rate limits are counted separately on each server instance, so they are approximate; and no security measure is perfect. Keep your API keys secret and rotate them if you think they have been exposed.
9. Accuracy
Your account information is what you gave us. If your email address changes, contact us and we will update it.
10. Your rights and how to use them
Email developwith.gt@gmail.com from the address on your account. If you write from another address, we will confirm by sending a message to the account address before acting. We do not charge for any request.
- Access. We will tell you what personal information we hold about you, how we use it and which providers process it, and give you a copy. We reply within 30 days. If we need more time we will tell you within those 30 days, and we will not take more than 30 additional days.
- Correction. We will correct inaccurate information, such as an outdated email address.
-
Deletion. You can delete your account yourself at any time: send
DELETE /v1/accountwith your live key and the body{ "confirm": "<your account email>" }. It removes your email, account record, keys, usage counts, tokens and webhooks from our database at once. Verification send records (section 4) are not linked to your account and hold no readable address; the hourly cleanup deletes each one, normally within 25 hours of the email and at most 48 hours, unless every hourly cleanup of a whole day fails (section 4), and then at the first run that succeeds. If you no longer have a key, email us and we will delete the account and the information listed in section 7 within 30 days of confirming the request, and tell you when it is done. - Portability. On request we will send your account information in JSON.
-
Keys. You can revoke or rotate your own keys at any time with
POST /v1/keys/revokeandPOST /v1/keys/rotate. - Withdraw consent as described in section 6.
If we refuse a request, we will tell you why and how to complain.
11. Breaches
If a breach of our safeguards involving your personal information creates a real risk of significant harm to you, we will report it to the Office of the Privacy Commissioner of Canada and notify you as soon as feasible, and tell anyone else who can reduce the harm where the law allows. We keep a record of every breach of security safeguards for at least 24 months.
12. Quebec residents
Takehome does not calculate Quebec payroll, but Quebec residents can use the site and sign up for the API. We apply the following to Quebec residents:
- The person in charge of the protection of personal information is Gautam Khosla, developwith.gt@gmail.com.
- This policy is our confidentiality policy. We will notify account holders of changes to it (section 15).
- We do not use technology that identifies, locates or profiles you.
- Your information is communicated outside Quebec to the providers in section 5.
- You may ask for access, correction, deletion and a copy in a structured, commonly used format (section 10). We reply within 30 days.
- If a confidentiality incident presents a risk of serious injury, we will notify the Commission d'accès à l'information and you, and we keep a register of incidents.
- You may contact the Commission d'accès à l'information du Québec at www.cai.gouv.qc.ca.
13. Children
Takehome is not directed at children. The calculators collect no personal information from anyone. API accounts are for developers and businesses; do not sign up if you are under 13. If we learn that a child under 13 has given us an email address, we will delete it.
14. If you embed the widget or send employee data through the API
-
Embedding sites. When a page includes our widget, the visitor's browser downloads
embed.jsand the calculation engine from our domain. Cloudflare receives the visitor's IP address, browser details and, as the embedding page's referrer policy allows, the embedding site's address. The salary shown in the widget is calculated in the visitor's browser and is not sent to us. The widget sets no cookies and stores nothing. If you embed the widget, tell your visitors that a script loads from takehome.gautamkhosla.com. - API customers. If you send information about your employees or clients through the API, you are responsible for having the authority to do so and for telling them as the law requires. We act as your service provider: we process each request only to return the calculation, and we keep nothing from it. Employees should direct questions about their payroll to their employer; we cannot identify anyone from requests because we keep none.
15. Changes to this policy
We will post any change here with a new "Last updated" date. If a change affects how we use account information in a material way, we will email account holders at least 30 days before it takes effect, unless the law requires a faster change, and we will ask for consent where the law requires it.
16. Contact and complaints
Contact Gautam Khosla at developwith.gt@gmail.com. We will answer within 30 days.
If you are not satisfied, you can complain to the Office of the Privacy Commissioner of Canada: www.priv.gc.ca/en/report-a-concern/ ; 30 Victoria Street, Gatineau, Quebec K1A 1H3; toll-free 1-800-282-1376; TTY 819-994-6591. The Commissioner asks that you first raise the issue with us.