Node.js
@tuago/node
The official, typed Node/TypeScript SDK. Every resource below maps 1:1 to the REST API, use whichever's easier to reach for.
Install
terminal
npm install @tuago/nodeindex.ts
import { Tuago } from "@tuago/node";
const tuago = new Tuago({
secretKey: process.env.TUAGO_SECRET_KEY!, // sk_test_… or sk_live_…
});tuago.live tells you whether the client was built with a live key, useful for a startup assertion in production code.
tuago.checkout, WhatsApp-native checkout
The flagship flow. Sessions are lazy, create() never touches the bank rail, only the payBy*call the customer's chosen method triggers does.
checkout.ts
await tuago.checkout.create(params, opts?) // → CheckoutSession
await tuago.checkout.get(id) // → CheckoutSession
await tuago.checkout.status(reference) // → { status, reference }
await tuago.checkout.payByBankTransfer(sessionId) // → BankTransferInstructions
await tuago.checkout.payByUssd(sessionId) // → UssdInstructions
await tuago.checkout.payByCard(sessionId, params) // → CardPaymentResult, server-side only, PCI scopeexample
const session = await tuago.checkout.create({
amount: 1850000, // kobo
customerEmail: "buyer@example.com",
mode: "headless",
subaccount: "sub_…", // optional, split settlement
transactionCharge: 100000, // optional, your platform cut override, kobo
});
// render session.paymentMethods in chat; once the customer picks one:
const instructions = await tuago.checkout.payByBankTransfer(session.id);tuago.charges, plain REST charges
charges.ts
await tuago.charges.create(params, opts?) // → Charge
await tuago.charges.get(reference) // → Charge
await tuago.charges.list(params?) // → Charge[]
await tuago.charges.verify(reference) // → Charge
await tuago.charges.requery(reference) // → Charge (pull missed transfers from the bank rail)example
const charge = await tuago.charges.create(
{ amount: 1850000, reference: orderId, subaccount: "sub_…", transactionCharge: 100000 },
{ idempotencyKey: orderId }, // safe retries, never double-charge
);
// render charge.virtualAccount in your own UI; confirmation arrives via webhooktuago.subaccounts, split settlement
For platforms (marketplaces, food-delivery apps, anyone collecting on behalf of vendors). One charge splits automatically between your platform cut and the vendor's own settlement account.
subaccounts.ts
await tuago.subaccounts.create(params) // → Subaccount, resolves + verifies the vendor's bank account
await tuago.subaccounts.get(id) // → Subaccount
await tuago.subaccounts.list(params?) // → Subaccount[]
await tuago.subaccounts.update(id, params) // → Subaccount
await tuago.subaccounts.settle(id) // → sweep this subaccount's payable to its bank nowtuago.refunds
refunds.ts
await tuago.refunds.create(params, opts?) // → Refund, full or partial; unwinds every split leg
await tuago.refunds.get(id) // → Refund
await tuago.refunds.list(params?) // → Refund[]Balance, settlements, banks
misc.ts
await tuago.balance.get() // → Balance
await tuago.settlements.list(params?) // → Settlement[]
await tuago.settlements.get(id) // → Settlement
await tuago.banks.list() // → Bank[]
await tuago.banks.resolve(bankCode, accountNumber) // → { accountName }Webhooks helper
webhook-route.ts
import { Tuago } from "@tuago/node";
app.post("/tuago-webhook", (req, res) => {
const event = Tuago.webhooks.constructEvent(
req.rawBody, // raw bytes, not the parsed body
req.headers["x-ollie-signature"],
endpointSecret,
);
if (event.type === "charge.success") { /* confirm the order */ }
res.sendStatus(200);
});Full signing details on the Webhooks page.
Errors
try-catch.ts
import { TuagoError } from "@tuago/node";
try {
await tuago.charges.create({ amount: 1850000 });
} catch (e) {
if (e instanceof TuagoError) {
console.log(e.code, e.httpStatus, e.message); // e.g. "merchant_cap_exceeded", 403
}
}Every stable code is listed on the Errors page, branch on e.code, not the message text.
Money is always integer minor units (kobo),
amount: 1850000 means ₦18,500.00. Never pass floats.