@cowriepay/sdk
v0.2.0
Published
Official CowriePay Node/TypeScript SDK: signed Developer API client + webhook verification.
Downloads
448
Maintainers
Readme
@cowriepay/sdk
Official CowriePay Node/TypeScript SDK: a signed client for the CowriePay Developer API (/v2) plus
webhook signature verification. Server-side only (your cpk_* secret must never reach a browser or
mobile app). Zero runtime dependencies (built on Node's fetch + crypto). Node ≥ 18.
Install
npm install @cowriepay/sdkQuickstart
import { CowriePay } from '@cowriepay/sdk';
const cowriepay = new CowriePay({
apiKey: process.env.CPK_KEY!, // cpk_test_… or cpk_live_…
apiSecret: process.env.CPK_SECRET!,
});
// One base URL for everything: https://api.cowriepay.io
// The key you use selects the network, no host switch:
// cpk_test_… → Sandbox (testnets: TRON Nile, BSC testnet, ETH Sepolia; fund from faucets)
// cpk_live_… → Live (mainnets, real funds)
// Same code for both; swap the key to go live. Override the host with { baseUrl } (e.g. a dev host).
// Typed resource namespaces: HMAC signing, retries, idempotency and typed errors are handled for you.
const wallet = await cowriepay.wallets.create(
{ chain: 'TRON', asset: 'USDT_TRON' },
{ idempotencyKey: crypto.randomUUID() }, // makes the POST safe to auto-retry
);
const { data: deposits } = await cowriepay.transactions.listDeposits({ status: 'CONFIRMED', limit: 20 });
const balances = await cowriepay.transactions.balances();
const withdrawal = await cowriepay.withdrawals.create({ /* ... */ } as any, { idempotencyKey: crypto.randomUUID() });Available namespaces: chains (the chains open for new operations, via cowriepay.chains.list()),
wallets, customers, transactions (deposits / withdrawals / balances),
withdrawals, fees, webhooks, apiKeys, health. Request/response shapes are fully typed from the
OpenAPI spec. For anything not yet wrapped, cowriepay.request({ method, path, body }) is a signed
escape hatch.
CowriePay ships WaaS-first: this SDK is generated from the WaaS-only API view, so it does not include the checkout surface (payment intents / refunds). Those namespaces appear automatically when checkout is launched and the full spec is published, no SDK redesign.
Errors
Every non-2xx response throws a typed error carrying the machine-readable code and HTTP status:
import { AuthenticationError, NotFoundError, RateLimitError, CowriePayError } from '@cowriepay/sdk';
try {
await cowriepay.request({ method: 'GET', path: '/wallets/does-not-exist' });
} catch (err) {
if (err instanceof NotFoundError) { /* 404 / FEATURE_NOT_AVAILABLE */ }
else if (err instanceof AuthenticationError) { /* 401 INVALID_SIGNATURE / TIMESTAMP_EXPIRED / … */ }
else if (err instanceof CowriePayError) { console.error(err.code, err.status, err.requestId); }
}Verifying webhooks
Verify against the raw request body (never a re-serialized object). During a secret rotation, pass both the current and previous secrets so no delivery is rejected while you roll the secret.
import { CowriePay } from '@cowriepay/sdk';
// e.g. Express with express.raw({ type: 'application/json' })
app.post('/webhooks/cowriepay', (req, res) => {
const ok = CowriePay.verifyWebhook({
payload: req.body, // Buffer or string, the RAW body
signatureHeader: req.header('X-CowriePay-Signature')!,
timestamp: req.header('X-CowriePay-Timestamp')!,
secrets: [process.env.WEBHOOK_SECRET!], // add the previous secret during rotation
toleranceSeconds: 300, // optional replay guard
});
if (!ok) return res.status(400).send('bad signature');
// ... handle req.header('X-CowriePay-Event')
res.sendStatus(200);
});Development
npm install
npm run gen:types # regenerate L1 types from ../../spec/openapi.yaml
npm run typecheck
npm test # golden vectors + prove-it-fails + client behaviour
npm run build # dual ESM + CJS + d.tsLicense
MIT, Copyright (c) 2026 COWRIEX SAS. See LICENSE.
CowriePay and COWRIEX are trademarks of COWRIEX SAS. This license covers the source code only and grants no right to the COWRIEX or CowriePay names or logos.
