1. Install
No npm package required — drop the file into your project and import it.
// Save as century-sdk.ts in your project.
import { CenturyClient } from "./century-sdk";
import { supabase } from "./supabase"; // your Supabase client
export const century = new CenturyClient({
baseUrl: "https://centuryvtu.com",
getAccessToken: async () => {
const { data } = await supabase.auth.getSession();
return data.session?.access_token ?? null;
},
});2. Use
// Wallet
const wallet = await century.wallet.getWalletState();
// Buy airtime (server verifies transaction PIN)
await century.vtu.buyAirtime({
network: "MTN",
phone: "080XXXXXXXX",
amount: 500,
pin: "1234",
});
// Start a Paystack top-up
const { authorizationUrl } = await century.payments.startPaystackTopup({
amount: 2000,
email: user.email,
callbackUrl: "myapp://pay/callback",
});
// Errors are typed
import { CenturyApiError } from "./century-sdk";
try {
await century.wallet.transfer({ username: "kene", amount: 1000, pin: "1234" });
} catch (err) {
if (err instanceof CenturyApiError && err.status === 401) {
// token expired
}
}Namespaces
client.authOTP + PIN login, session claim/heartbeat
client.twoFactorTOTP enrollment, step-up challenges, grants
client.walletBalance, top-up intents, debit, transfer, username lookup
client.paymentsPaystack init/verify, receipts, history
client.vtuAirtime, data, cable, electricity, betting, exam pins
client.kycTier 1 liveness, Tier 2 NIN, Tier 3 bank + ID document
client.notificationsInbox, broadcasts, poll voting
client.pushVAPID key + subscribe/unsubscribe
client.settingsPreferences, transaction PIN, close account
client.growthReferrals, milestones, daily check-in
client.savingsLock, break, list
client.marketplaceOrders CRUD
client.subscriptionsNetflix / Spotify / etc. orders
client.supportThread + messages
client.schedulesRecurring purchases
client.reportsTransaction dispute reports
client.receiptsSign & verify receipts
Error handling
Every non-2xx response throws CenturyApiError with status, message, and the parsed body. Common statuses:
400— validation failed (input didn't match schema).401— missing/expired bearer token or wrong PIN.403— KYC tier too low, account frozen, or route not available to your account.429— rate limited (back off and retry).500— unexpected server error (an error ID is logged).
Low-level escape hatch
// Call any server function by name — useful for beta endpoints.
const anything = await century.invoke("listMyVtuTransactions", undefined, "GET");