TypeScript SDK
The official TypeScript client — @crylabsorg/suward-sdk. A typed client over the full merchant API, plus WebhooksHelper for signature verification.
Install
npm install @crylabsorg/suward-sdkCreate a client
import { SuwardSDKClient } from "@crylabsorg/suward-sdk";
export const suward = new SuwardSDKClient({
apiKey: process.env.SUWARD_API_KEY, // server-side only
});The quickstart flow, in TypeScript
// 1 — create a payment for one order
const payment = await suward.payments.createPayment({
amount: "100000000", // integer string, smallest unit
asset: "TESTSTABLECOIN_OPTIMISM",
externalId: order.id, // makes the call idempotent
});
// 2 — projects with an activation flow start the payment in pending/created,
// with no address and no way into accepted until it is activated
if (payment.subStatus === "created") {
await suward.payments.activatePayment({ paymentId: payment.id });
}
// 3 — send the customer to the hosted checkout
redirect(payment.paymentPageUrl);
// 4 — drive the lifecycle while you write the handler (test assets only)
await suward.payments.simulatePayment({
paymentId: payment.id,
status: "accepted",
subStatus: "completed",
});
// 5 — read the authoritative state whenever you need it
const fresh = await suward.payments.getPayment({ paymentId: payment.id });Quote before you create
const quote = await suward.payments.quotePaymentFees({
asset: "USDT_ARBITRUM",
amount: "100000000",
serviceFeePayer: "customer",
networkFeePayer: "customer",
complianceLevel: "basic",
});
console.log(quote.gross, quote.netAmount, quote.fee, quote.networkFee);Static wallets
const wallet = await suward.staticWallets.createStaticWallet({
externalId: `customer-${user.id}`,
allowedAssets: ["USDT_ETHEREUM", "USDT_ARBITRUM"],
});
const deposits = await suward.staticWallets.listStaticWalletDeposits({ staticWalletId: wallet.id, limit: 100 });Verify webhooks
import { webhooks } from "@crylabsorg/suward-sdk";
const ok = await webhooks.WebhooksHelper.verifySignature(
rawBody, // string — never the parsed object
headers["x-suward-signature"],
process.env.SUWARD_WEBHOOK_PUBLIC_KEY,
headers["x-suward-timestamp"]
);The helper checks the X-Suward-Timestamp header against a 300-second tolerance as well as the signature, so pass the header through as received. Full handler, including the required deduplication on eventId → Webhooks.
Errors
import { SuwardSDKError } from "@crylabsorg/suward-sdk";
try {
await suward.payments.createPayment({ amount: "0", asset: "USDT_ARBITRUM" });
} catch (e) {
if (e instanceof SuwardSDKError) {
const body = e.body as { errorCode?: number; message?: string } | undefined;
console.error(e.statusCode, body?.errorCode, body?.message);
if (e.statusCode === 409) { /* externalId already used — fetch it instead */ }
}
throw e;
}Codes and retry rules → Errors & limits.
Something unclear? payments@suward.com — we treat every integration question as a documentation defect.