TypeScript SDK
Learn how to install, configure, and use our TypeScript SDK.
The WinWinKit TypeScript SDK is a thin, promise-based wrapper around the REST API. It works in any modern JavaScript runtime — React, React Native, Expo, Node.js, and others. Every call resolves to a discriminated union: either the data you asked for, or an errors array.
Installation
Requirements
- A modern JavaScript runtime (Node.js 18+ or an evergreen browser).
- TypeScript types are bundled — no
@types/*package needed.
Package
The SDK is published to npm as @winwinkit/sdk. Install it with the package manager of your choice.
pnpm
pnpm add @winwinkit/sdk npm
npm install @winwinkit/sdk yarn
yarn add @winwinkit/sdk bun
bun add @winwinkit/sdk You can now import { WinWinKit } from "@winwinkit/sdk" from any source file.
Configuration
Instantiate WinWinKit once with your API key. Use an API Key from the WinWinKit dashboard (Settings → Integrations → API Keys).
import { WinWinKit } from "@winwinkit/sdk";
const wwk = new WinWinKit({
apiKey: process.env.WINWINKIT_API_KEY!,
}); Hold on to this instance — typically as a module singleton or a DI-provided value — and reuse it across the app.
The SDK is stateless: every method takes the appUserId of the user the call
applies to. Make sure you pass the correct id at each call site so activity
isn’t attributed to the wrong user.
Use a UUID-like value for the app user id — never an email, phone number, username, or any other personally identifying information. The id ends up in URLs, logs, and analytics, so treat it as a public identifier.
If your app has no sign-in flow, generate a random UUID on first launch and
persist it in localStorage (web), secure storage (React Native, Expo), or
similar.
Create a user
Register the user in WinWinKit with createOrUpdateUser(...) before calling claimCode or any other user-related action.
const { user, errors } = await wwk.createOrUpdateUser({
appUserId: "your-app-user-id",
}); All arguments other than appUserId are optional. To set writable fields at creation time, see User properties.
Claim a code
Call claimCode(...) when a user enters a code in your app — typically from a “Got a referral code?” screen, a referral link landing flow, or a deep link handler.
Pass the code exactly as the user entered it — WinWinKit validates it and returns errors if it’s unknown, expired, ineligible, or already claimed. On success the response includes the updated User and any rewards granted at claim time.
const { user, rewardsGranted, errors } = await wwk.claimCode({
appUserId: "your-app-user-id",
code: "XYZ123",
});
if (errors) {
// Show errors — see Error handling below.
} else {
// Apply granted rewards in your app.
} Grant user rewards
The User object is the source of truth for what the user is entitled to in WinWinKit — claimed codes, active rewards, and stats. Fetch it whenever you want a fresh snapshot to unlock the matching perks in your app.
const { user } = await wwk.fetchUser({ appUserId: "your-app-user-id" });
// Inspect user?.rewards.active and grant features accordingly. What you do with each reward depends on its type:
- Basic — flip a feature flag or unlock content in your app.
- Credit — apply the balance; call
withdrawCreditswhen the user spends it. - App Store Offer Code / Google Play Promo Code — present the code to the user or trigger the platform redemption flow.
- RevenueCat Entitlement — read the entitlement state from RevenueCat and unlock the corresponding feature.
- RevenueCat Offering — display the matching paywall offering.
The SDK is stateless — it doesn’t cache the user. Store the result yourself (e.g. in React state or a store) so your UI can react when it changes.
User object
The User object exposes properties you can update from the SDK and properties WinWinKit manages for you.
Updatable
Update writable fields with createOrUpdateUser(...). All arguments other than appUserId are optional — pass only what you want to change.
const { user, errors } = await wwk.createOrUpdateUser({
appUserId: "your-app-user-id",
isPremium: true,
isTrial: false,
firstSeenAt: new Date(),
metadata: { plan: "annual", platform: "web" },
}); Is Premium
Marks the user as a paying customer. Drives conversion tracking, affiliate commissions, and reward activation.
Is updated automatically when revenue tracking is configured — directly from App Store, or Google Play, and from RevenueCat, Stripe. Configure them in Settings → Integrations.
Is Trial
Marks the user as currently on a free trial. Conversions are not counted while a user is in trial.
Is updated automatically when revenue tracking is configured — directly from App Store, or Google Play, and from RevenueCat, Stripe. Configure them in Settings → Integrations.
First Seen At
The “first seen at” date controls claim code eligibility (default window: 7 days). If you don’t set it, WinWinKit uses the user’s creation date.
Metadata
Attach arbitrary key-value pairs to a user.
Provided by WinWinKit
These properties are managed by WinWinKit. Read them from the User returned by fetchUser(...) or createOrUpdateUser(...).
Referral Code
The user’s own referral code, generated when they are created in WinWinKit.
"referral_code": "ABC123" Referral Code Link
A hosted Code Link URL to the user’s referral code.
"referral_code_link": "https://example.wwk.link/ABC123" Claim Code Eligibility
Whether the user can claim a code right now, and until when.
{
"eligible": true,
"eligible_until": "2026-05-05T12:00:00Z"
} See Claim Code Eligibility for the rules.
Referred By
The code that referred this user, if any. type is one of affiliate, promo, or referral.
{
"code": "XYZ123",
"type": "referral"
} Stats
Counters for users who claimed this user’s referral code: total claims, conversions to premium, and subsequent churns.
{
"claims": 12,
"conversions": 5,
"churns": 1
} Rewards
The user’s active and expired rewards, grouped by reward type.
{
"active": {
"basic": [...],
"credit": [...],
"offer_code": [...],
"googleplay_promo_code": [...],
"revenuecat_entitlement": [...],
"revenuecat_offering": [...]
},
"expired": {
"basic": [...],
"credit": [...],
"offer_code": [...],
"googleplay_promo_code": [...],
"revenuecat_entitlement": [...],
"revenuecat_offering": [...]
}
} Referral Program
The referral program the user is part of, if any.
Methods
Withdraw credits
Spend down a credit reward balance. The amount is debited from the user’s available credit for the given key. operationId is optional and lets you make the call idempotent — passing the same id twice debits only once.
const { user, withdrawResult, errors } = await wwk.withdrawCredits({
appUserId: "your-app-user-id",
key: "extra-levels",
amount: 5,
operationId: "checkout-7d3a",
}); Register App Store transaction
Register an App Store transaction with WinWinKit. Only needed when using direct App Store revenue tracking (without RevenueCat integration) — call this after a purchase completes so WinWinKit can attribute the conversion without delays.
const { errors } = await wwk.registerAppStoreTransaction({
appUserId: "your-app-user-id",
originalTransactionId: "1000000123456789",
}); Register Google Play transaction
Register a Google Play purchase with WinWinKit. Only needed when using direct Google Play revenue tracking (without RevenueCat integration) — call this after a purchase completes so WinWinKit can attribute the conversion without delays.
const { errors } = await wwk.registerGooglePlayTransaction({
appUserId: "your-app-user-id",
purchaseToken: "abc...token",
}); Refresh
To refresh the user’s state, call fetchUser(...) again.
const { user } = await wwk.fetchUser({ appUserId: "your-app-user-id" }); Error handling
Every method resolves to a discriminated union — the SDK never throws on API errors. Check the errors field to branch:
const { user, errors } = await wwk.fetchUser({ appUserId: "your-app-user-id" });
if (errors) {
// errors is ErrorObject[] — show, log, or surface them.
} else {
// user is User | null — null means the user does not exist (HTTP 404).
} The shape per method:
- Most methods —
{ ...payload, errors: null } | { ...payload-fields-as-null, errors: ErrorObject[] }. fetchUser— additionally returns{ user: null, errors: null }when the user does not exist.registerAppStoreTransaction/registerGooglePlayTransaction— return only{ errors: ErrorObject[] | null }.
Network failures and unexpected runtime errors will reject the returned promise — wrap calls in try/catch if you need to handle those distinctly from API errors.
See Errors for the full list of error codes the API can return.