Quickstart
This guide takes you from zero to a working iframe inside your app. It assumes you already have a CoinTracker partner agreement and credentials to mint JWTs — if not, reach out to your CoinTracker integration owner to kick that off. See Integration planning for what to bring to kickoff.
Before you start
You'll need:
- An active CoinTracker partner integration — your slug enrolled, credentials issued. See Integration planning.
- JWT-minting credentials from your CoinTracker integration owner — these go on your backend, never in the browser.
- A React 16.8+, 17, 18, or 19 frontend with the part of your app where the kit should live identified.
- A backend endpoint you control that can exchange your partner credentials for a CoinTracker JWT.
- Browser-policy headers compatible with the iframe on the page that renders the kit:
- CSP — your
frame-srcdirective must allowhttps://embedded.cointracker.com(or the staging origin if you're using it). If you don't set a CSP at all, you're already fine. - Permissions-Policy — the iframe requests
clipboard-write(for copy-to-clipboard) andpayment(for the subscription/upgrade flow). The SDK sets the iframe'sallowattribute automatically — you only need to take action if your parent page sets a strict Permissions-Policy that blocks these features from being delegated to iframes.
- CSP — your
Browser support: the kit targets evergreen Chromium, Firefox, Safari, and their mobile equivalents. iOS Safari 15+ and Android Chrome 100+ are the practical floors.
- 1
Install the package
npm install @cointracker/tax-kit# orbun add @cointracker/tax-kitSupported React versions: 16.8+, 17, 18, 19.
- 2
Implement the token handler on your backend
Your backend exchanges your partner credentials with CoinTracker for a short-lived JWT and returns it to your frontend. The exact shape of the request to CoinTracker is partner-specific — your CoinTracker integration contact will provide the endpoint and required claims.
// Example partner backend handler (Express-style pseudocode)app.post('/api/cointracker-token', async (req, res) => {const token = await mintCointrackerJwt({partnerUserId: req.session.userId,// …additional claims required by your CoinTracker integration});res.json({ access_token: token });});warningNever expose your partner credentials to the browser. The JWT must be minted server-side and returned to the frontend over an authenticated channel.
- 3
Mount TaxKitProvider above the tax page
Mount
TaxKitProviderabove the route or component subtree that needs the kit — typically your tax-center page. The iframe is positionedfixedand covers the viewport when opened, so it doesn't matter where exactly in the DOM the provider sits — only that it's a React ancestor of any component callinguseTaxKit().import { TaxKitProvider } from '@cointracker/tax-kit';export default function TaxCenterPage() {const fetchAccessToken = async () => {const res = await fetch('/api/cointracker-token', { method: 'POST' });const { access_token } = await res.json();return access_token;};return (<TaxKitProvider fetchAccessToken={fetchAccessToken}><YourTaxCenterContent /></TaxKitProvider>);}fetchAccessTokenis the only required prop. The provider calls it whenever the iframe needs to authenticate — including when the existing token is within 30 seconds of expiry.Where to mount it: scope the provider as narrowly as the kit actually needs to be reachable. Wrapping it around your tax-center route is the common case. Wrapping the entire root app works but mounts the iframe (and the post-robot bridge) on every page — wasted work on pages that don't use the kit.
- 4
Open the kit from a button
import { useTaxKit } from '@cointracker/tax-kit';function TaxCenter() {const { open, numberOfConnections, taxKitStatus } = useTaxKit();return (<button onClick={open}>{numberOfConnections != null? `Open Tax Kit (${numberOfConnections} connection${numberOfConnections === 1 ? '' : 's'})`: 'Get started'}</button>);}