Skip to main content
This guide covers credentials, installing the SDK, and how it is organised. When you are ready to wire sign-in, continue with Set up OAuth authentication, then Fetch offers, then Display offer details. Examples use Next.js App Router patterns; you can adapt the same pieces to other React frameworks as long as you have a dedicated backend.
Clone the Partner Demo GitHub repo and follow this tutorial alongside the running example integration. You see it live at partner.coinlist.dev.

Get OAuth credentials

You need values from Passage before you write code:
  • client_id - public identifier for your app
  • redirect_uri - exact callback URL registered with Passage (must match what you pass in the SDK)
  • client_secret - server-only; never expose this to the browser or commit it to frontend bundles
Request access and registration through Support or your Passage contact. Store secrets in server environment variables (for example COINLIST_CLIENT_SECRET), and use NEXT_PUBLIC_ only for values that are safe in the client (typically client_id and redirect_uri).

Install the SDK

Peer dependencies: react and react-dom >= 18, and viem ^2 (added in v0.9.0 for the on-chain flows). See Package overview for all import paths and the full namespace map.

How the SDK is organised

The SDK splits three ways, in this order: environment, then level, then feature. Learn those three and you can find anything in it.

Level: how much you want to build

Every feature is available at several levels. Each rung down hands you more control and asks for more code from you. Start at the top and descend only when you need to.
  1. L3 - React components (highest). You get UI and behavior together, working. You provide the input and a config object, and you are done. <CheckoutContainer offer chain wallets config /> is an entire purchase flow: wallet selection, amount entry, approval, review, confirmation. Others: <OffersGridContainer>, <RequirementsChecklistContainer>, <CoinListSignInCardContainer>.
  2. L2 - React hooks (mid). You get the behavior: data fetching, state, polling, error handling, and the on-chain sequencing. You provide the UI. useOffers() hands you a LOADING / ERROR / CONTENT state machine and you render whatever you like from it; useOndoBuyCheckoutViewModel() runs the whole Ondo flow behind your own markup.
  3. L1 - TypeScript clients (low). You get the logic: typed API calls, domain mapping, and total on-chain flows that return a step-tagged result instead of throwing. You build the state management and the UI. CoinListClient in the browser, CoinListServer on your backend, no React anywhere. Use it for a non-React app, a custom state layer, or full control.
Below L1 there is no SDK. If you need something the client does not model, call the HTTP API directly. A feature may stop at a rung, but it never skips one. CoinList token sales are L1 and L2 only today: there is a namespace and a hook, but no component yet, so that flow’s UI is yours to render.

Environment: where code runs

Environment comes first in the split because it is a security boundary, not a convenience: CoinListServer holds your client_secret, and it must never reach a browser bundle. That boundary is exactly the three import paths you type. The gaps in that grid are the point. L2 and L3 exist only in the browser, because a backend renders nothing. L1 is the only level present everywhere, which is why coinlist.offers.list() reads the same on your server as in your React tree.

Feature

Inside each level, the code is grouped by feature, and the same four words appear at every rung: auth, offers, requirements, checkout. So coinlist.requirements (L1), useRequirements() (L2) and <RequirementsChecklistContainer> (L3) are three rungs of one ladder, not three unrelated APIs. Checkout is grouped one level deeper, by provider and product - Superstate swap, Ondo buy, CoinList token sale - because every provider’s flow differs in roughly a fifth of its substance. <CheckoutContainer> is what saves you from caring: it routes on offer.type so you integrate once.
Recommendation: start with components, drop to hooks when you need custom UI, and reach for the clients when you are outside React or need full control. The HTTP API remains the contract underneath, for bespoke stacks or endpoints the SDK does not wrap yet.

Next step

SDK structure

The patterns every part of the SDK follows: namespaces, containers, hook state, and flows that return instead of throwing. Skippable if you would rather start building.
After OAuth, follow Fetch offers to render OffersGridContainer, then Display offer details for a single offer. Then Requirements for what a user must satisfy before participating, Wallets to plug in your wallet stack, and Building the Checkout flow to render the purchase itself. Use the API reference when you need raw request and response details.