Node.js SDK @watenga/node
Node 18 or later; TypeScript types included.
Installation
npm install @watenga/nodeBefore the first release
pnpm --filter @watenga/node build && cd packages/watenga-node && npm pack
npm install /path/to/watenga-node-1.0.0.tgzTake a test payment
Use a test secret key (sk_test_…) from the developer console. Test keys never move money: use the test cards and wallet numbers.
import Watenga from '@watenga/node';
const watenga = new Watenga(process.env.WATENGA_SECRET_KEY!); // sk_test_...
const checkout = await watenga.checkout.create({
amount: '25.00',
currency: 'USD',
merchant_transaction_id: 'ORD-1001',
return_url: 'https://shop.example/return',
});
// Send the buyer to checkout.payment_urlReceive the webhook
Verify the Watenga-Signature header against the raw request body before you trust an event. While you rotate the endpoint's signing secret, pass both secrets: either one verifies. On your machine, watenga listen --forward-to <your URL> (the CLI) forwards test events signed with a session secret.
import express from 'express';
import { Webhooks } from '@watenga/node';
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
let event;
try {
event = Webhooks.constructEvent(req.body, req.headers['watenga-signature'] as string, process.env.WATENGA_WEBHOOK_SECRET!);
} catch {
return res.sendStatus(400);
}
if (event.type === 'payment.capture.completed') {
// fulfil the order for event.data.object (a transaction)
}
res.sendStatus(200);
});Errors
Every failed call raises one error type with the stable code, the HTTP status, the request_id to quote to support, the field at fault (param) and the code's page in the error reference.
import { WatengaApiError } from '@watenga/node';
try {
await watenga.refunds.create('txn_...', { amount: '5.00', reason: 'customer_request' });
} catch (err) {
if (err instanceof WatengaApiError) {
console.error(err.code, err.statusCode, err.param, err.requestId, err.docUrl);
}
}Retries and idempotency
Network errors, 429 (after Retry-After) and 5xx answers are retried twice with backoff. Every write carries an Idempotency-Key, kept across those retries, so a retry is answered once and never applied twice; checkout.create uses checkout:<merchant_transaction_id>. See Idempotency.
// Every write gets an Idempotency-Key, kept across the SDK's own retries.
// When you retry a call yourself, pass the same key:
await watenga.refunds.create('txn_...', { reason: 'duplicate' }, { idempotencyKey: 'refund-ORD-1001' });Pagination
Every list answers one page, { object: "list", data, has_more, next_cursor }; the auto-paginating form reads them all. See Pagination.
const page = await watenga.transactions.list({ status: 'completed', limit: 50 });
// { object: 'list', data: [...], has_more, next_cursor }
for await (const txn of watenga.transactions.listAll({ status: 'completed' })) {
console.log(txn.id, txn.amount, txn.currency);
}Resources
The SDK sends Watenga-Version: 2026-10-29; fields use the API's names (snake_case) and money is a decimal string. The same method names in every language.
| Resource | Methods |
|---|---|
checkout | create, getStatus |
checkoutSessions | create, retrieve, expire |
transactions | list, listAll, retrieve, getMobileStatus |
refunds | create |
paymentLinks | create, list, listAll, retrieve, update, deactivate, clone, versions, analytics |
invoices | create, list, listAll, retrieve, update, send, remind, void, templates |
quotations | create, list, listAll, retrieve, update, issue, revise, void, duplicate, convertToInvoice |
plans | create, list, listAll, retrieve, update, del |
subscriptions | create, list, listAll, retrieve, cancel, pause, resume, change, upcomingInvoice, listInvoices, events |
billing | recordUsage, reverseUsage, checkEntitlement |
customers | create, list, listAll, retrieve, update, timeline, setTag, paymentMethods |
paymentMethods | create, list, listAll, retrieve, del, charge |
account | getBalance, getProfile, getApiKey |
automations | list, retrieve, listRuns, retrieveRun, registry, dryRun (read-only) |
webhooks | constructEvent, generateTestSignature |
Refunds and payouts
refunds scope (Refunds). Payouts to your bank are dashboard-only, with two-step verification: they are not in the API or the SDKs.