The official TypeScript SDK for the PayArk payment gateway API.
Zero dependencies · Type-safe · Retry-safe (idempotent) · Node 18+ / Bun / Deno
# npm
npm install @payark/sdk
# bun
bun add @payark/sdk
# pnpm
pnpm add @payark/sdkimport { PayArk } from "@payark/sdk";
// Environment is automatically detected by the key prefix
const payark = new PayArk({ apiKey: "sk_test_..." }); // Automatically uses Sandbox Mode
// const payark = new PayArk({ apiKey: "sk_live_..." }); // Automatically uses Live Mode
// Create a checkout session
const session = await payark.checkout.create({
amount: 500,
provider: "esewa", // or "khalti", "hamropay"
returnUrl: "https://your-site.com/thank-you",
});
// Redirect user to the hosted checkout page
console.log(session.checkout_url);
// → "https://payark.dev/checkout/pay_abc123"const payark = new PayArk({
apiKey: "sk_test_...", // Required – your project secret key (sk_test_ or sk_live_)
baseUrl: "https://api.payark.dev", // Optional – for local dev
timeout: 10_000, // Optional – request timeout in ms (default: 30s)
maxRetries: 2, // Optional – retries on 5xx errors (default: 2)
sandbox: true, // Optional – explicit Sandbox Mode override (recommended: use sk_test_ instead)
});PayArk uses Key-Driven Environment Switching. You no longer need to manually toggle sandbox modes in your code—simply provide the appropriate key.
- Sandbox (Test Mode): Use an
sk_test_...key. Payments are simulated, no real money is moved, and you can test without real provider credentials. - Live (Production Mode): Use an
sk_live_...key. Real money transactions via configured payment gateways.
When using an sk_test_ key, if you haven't added your own credentials (e.g., eSewa UAT keys) to the project, PayArk defaults to the Sandbox Provider. This allows you to test the full checkout flow immediately after registration.
Create a new payment checkout session.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount |
number |
✅ | Payment amount in the base currency unit |
provider |
'esewa' | 'khalti' | 'hamropay' |
✅ | Payment provider |
returnUrl |
string |
✅ | URL to redirect after successful payment |
currency |
string |
❌ | ISO currency code (default: "NPR") |
cancelUrl |
string |
❌ | URL to redirect on cancellation |
metadata |
Record<string, unknown> |
❌ | Arbitrary metadata (e.g. order_id) |
Returns: Promise<CheckoutSession>
interface CheckoutSession {
id: string;
checkout_url: string;
payment_method: {
type: "esewa" | "khalti" | "hamropay";
url?: string;
method?: "GET" | "POST";
fields?: Record<string, string>;
};
}List payments for the authenticated project.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
number |
❌ | Max records (1–100, default: 10) |
offset |
number |
❌ | Pagination offset (default: 0) |
Returns: Promise<PaginatedResponse<Payment>>
const { data, meta } = await payark.payments.list({ limit: 25 });
console.log(`Total: ${meta.total}`);Retrieve a single payment by ID.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string |
✅ | Payment identifier (pay_...) |
Returns: Promise<Payment>
const payment = await payark.payments.retrieve("pay_abc123");
console.log(payment.status); // → "success"Securely verify and parse incoming webhooks.
| Parameter | Type | Required | Description |
|---|---|---|---|
body |
string |
✅ | The raw request body string |
signature |
string |
✅ | The X-PayArk-Signature header |
secret |
string |
✅ | Your webhook signing secret (whsec_...) |
Returns: Promise<WebhookEvent>
// Example for Hono/Node.js
const body = await req.text(); // Raw body is required
const sig = req.headers.get("x-payark-signature");
try {
const event = await payark.webhooks.constructEvent(
body,
sig,
process.env.PAYARK_WH_SECRET,
);
if (event.type === "payment.succeeded") {
const payment = event.data;
// Provision services here
}
} catch (err) {
// Signature verification failed or body is malformed
}All errors thrown by the SDK are instances of PayArkError, which extends Error with structured metadata.
import { PayArk, PayArkError } from '@payark/sdk';
try {
await payark.checkout.create({ ... });
} catch (err) {
if (err instanceof PayArkError) {
console.error(err.code); // "authentication_error"
console.error(err.statusCode); // 401
console.error(err.message); // "Unauthorized: Invalid API Key"
console.error(err.raw); // Original API error body
// Structured logging
console.log(JSON.stringify(err.toJSON()));
}
}| Code | HTTP Status | Description |
|---|---|---|
authentication_error |
401 | Invalid or missing API key |
permission_error |
403 | Valid auth but insufficient permissions |
invalid_request_error |
400 / 422 | Bad request parameters |
not_found_error |
404 | Resource not found |
rate_limit_error |
429 | Too many requests |
api_error |
500+ | Server-side failure |
connection_error |
— | DNS, timeout, or connection error |
The SDK automatically retries:
- Server errors (
500,502,503,504) with exponential back-off and jitter. - Rate limits (
429) only when the API provides a validRetry-Afterheader.
Other client errors (4xx) fail immediately since they are deterministic.
- Default: 2 retries
- Back-off: 500ms → 1s → 2s (+ random jitter)
- Set
maxRetries: 0to disable
Idempotency: All mutating requests (POST, PUT, PATCH) automatically include an Idempotency-Key header. The same key is reused across retry attempts for a given call, ensuring that retried payments are never accidentally duplicated.
The SDK is written in TypeScript and ships with full type declarations.
All types are available for import:
import type {
PayArkConfig,
CreateCheckoutParams,
CheckoutSession,
Payment,
PaymentStatus,
Provider,
PaginatedResponse,
PayArkErrorBody,
} from "@payark/sdk";# Install dependencies
bun install
# Run tests
bun test
# Build (CJS + ESM + types)
bun run build
# Type check
bun run linttests/
├── unit/
│ ├── errors.test.ts – Error class + factory mapping
│ ├── http.test.ts – HTTP transport, retries, idempotency, timeouts
│ ├── sandbox.test.ts – Sandbox Mode header injection
│ └── client.test.ts – PayArk client, resources, request construction
└── integration/
└── sdk.test.ts – End-to-end workflows (checkout → payment → recovery)
For users of the Effect ecosystem, we provide a dedicated package @payark/sdk-effect.
This package offers a fully functional, type-safe API with:
- Zero Promise overhead: Uses
@effect/platform/HttpClientnatively. - Runtime Validation: Validates all responses using
@effect/schema. - Typed Errors: Tagged errors for clean matching.
- Observability: Built-in support for Effect's tracing and spans.
bun add @payark/sdk-effectSee the @payark/sdk-effect documentation for more details.
MIT