Runtime-agnostic TypeScript client for the WATA payment gateway API.
Works with Node.js 18+, Bun, and Deno. Zero dependencies - uses the global fetch and Web Crypto APIs.
# npm
npm install wata-pay
# bun
bun add wata-pay
# jsr (deno)
deno add jsr:@omnifaced/wata-payimport { WataPayApi } from "wata-pay";
const api = new WataPayApi("your-bearer-token");
const link = await api.createLink({
amount: 1500,
currency: "RUB",
orderId: "order-42",
description: "Premium subscription",
});
console.log(link.url);const api = new WataPayApi("your-sandbox-token", "sandbox");// Create a payment link
const link = await api.createLink({
amount: 1000,
currency: "RUB",
type: "OneTime",
description: "Test payment",
successRedirectUrl: "https://example.com/success",
failRedirectUrl: "https://example.com/fail",
expirationDateTime: "2026-12-31T23:59:59Z",
});
// Get a single link
const existing = await api.getLink("link-id");
// Search links with filters
const { items, totalCount } = await api.getLinks({
currencies: "RUB",
statuses: "Opened",
sorting: "creationTimedesc",
maxResultCount: 10,
});// Get a single transaction
const transaction = await api.getTransaction("transaction-id");
// Search transactions
const { items } = await api.getTransactions({
statuses: "Paid",
amountFrom: 500,
sorting: "amountdesc",
});const refund = await api.createRefund({
originalTransactionId: "transaction-id",
amount: 500,
});const { value } = await api.getPublicKey();Register handlers for webhook events and verify incoming requests:
api
.on("pre_payment", (payload) => {
console.log("Payment initiated:", payload.transactionId);
})
.on("post_payment", (payload) => {
console.log("Payment completed:", payload.transactionId, payload.transactionStatus);
})
.on("refund", (payload) => {
console.log("Refund processed:", payload.transactionId);
});
// In your HTTP handler:
const isValid = await api.handleWebhook(rawBody, request.headers["x-signature"]);
if (!isValid) {
return new Response("Invalid signature", { status: 403 });
}The public key is fetched automatically on the first handleWebhook call and cached. Signature verification uses RSA-SHA512 via the Web Crypto API.
import { WataApiError } from "wata-pay";
try {
await api.createLink({ amount: -1, currency: "RUB" });
} catch (error) {
if (error instanceof WataApiError) {
console.log(error.statusCode); // 400
console.log(error.code); // "PL_1001"
console.log(error.message); // "Your request is not valid!"
console.log(error.details); // Additional details
console.log(error.validationErrors); // [{ message: "...", members: ["amount"] }]
}
}import { verifyWebhookSignature } from "wata-pay";
const isValid = await verifyWebhookSignature(pemPublicKey, base64Signature, rawBody);All request/response types are exported and fully documented with JSDoc:
import type {
Currency,
LinkType,
LinkStatus,
TransactionStatus,
TransactionType,
TransactionKind,
WebhookEvent,
WataNetwork,
CreateLinkParams,
SearchLinksParams,
PaymentLink,
PaymentLinkListItem,
SearchTransactionsParams,
Transaction,
CreateRefundParams,
RefundResponse,
PublicKeyResponse,
WebhookPayload,
WataErrorBody,
PaginatedResponse,
} from "wata-pay";MIT