Token Purchase Platform API
Sell tokens for stablecoins without touching wallets, gas, or smart contracts directly. Modeled on popular Payment Intents APIs: create a TokenPurchaseIntent, a hosted widget confirms it on-chain, and a webhook tells you what actually happened.
Official SDKs
We maintain an official Node.js SDK to make integrating with this API easier. You can install it via npm:
npm install @shake-defi/node
View the package on npm: @shake-defi/node
Authentication
Pass your secret key in the Authorization header on every server-side
request:
Authorization: Bearer sk_live_51Hxyz...
Two key types exist:
| Prefix | Used in | Can do |
|---|---|---|
sk_test_ / sk_live_ |
Your backend | Create and retrieve resources |
pk_test_ / pk_live_ |
Your frontend (checkout widget) | Initialize the widget only |
Never expose a secret key (sk_…) to the frontend.
Initializing the checkout widget
POST /token_purchase_intents returns two things a frontend can use to
drive the widget — pass exactly one to your widget SDK:
-
_widget_params— a snapshot taken at intent-creation time. No further API calls required. -
client_secret— a bearer credential ({intent_id}_secret_{random}) the widget exchanges for live params, including the current on-chain price, via the publicGET /widget/paramsendpoint below. Safe to send to the browser by design, but treat it like any other credential: don't log it, and don't let one customer see another's.
GET /widget/params deliberately requires no API key — possession of the
client_secret is the only authorization, mirroring the standard
PaymentIntent client_secret pattern.
Test vs. live mode
Every object carries a livemode boolean. Which mode you're in is
determined entirely by which key you use — no separate network parameter.
Test mode runs on Base Sepolia with test stablecoins; live mode runs on
Base mainnet with real stablecoins. Test and live objects are fully
isolated from each other.
Supported payment currencies
The currencies accepted by your account are listed under currency_contracts
in the GET /account response. Pass the currency symbol (e.g. "USDC",
"USDT") as payment_currency when creating an intent. Attempting to use
an unsupported currency returns a 400 with code missing_required_param.
Token amounts
token_amount_estimate and token_amount are ERC-20 token amounts in
18-decimal wei units and can exceed JavaScript's safe integer range
(Number.MAX_SAFE_INTEGER). Clients must treat these fields as
arbitrary-precision integers (e.g. BigInt in JS, BigInteger in Java,
int in Python 3). They are typed integer with format: uint256 here
as a signal; deserialise them accordingly.
Payment amounts
amount and price_snapshot are human-readable decimals — 5.00
means $5.00 USD equivalent. Do not multiply by 10^6.