JavaScript SDK

Alpha — under active development. Every alpha release may include breaking changes. Pin exact versions during alpha.
Official TypeScript SDK for Vatly, the European Merchant of Record for AI, software and digital products. Create checkouts and manage customers, subscriptions, and orders from your server.
For all endpoint fields and options, see the API reference. The OpenAPI spec is also available for tooling.
Installation
Pin the published alpha version:
npm install --save-exact @getvatly/sdk@0.3.0-alpha.4
# or: pnpm add --save-exact @getvatly/sdk@0.3.0-alpha.4
The package ships ESM + CommonJS builds and its own TypeScript types. It uses the
platform fetch and Web Crypto — no axios, node-fetch, or node:crypto — so
it can run on Node and modern edge hosts. Keep API keys on the server.
Quick start
Initialize the client with your API key and create a checkout.
API Keys
Get your API keys from the Vatly Dashboard under Settings > API.
| Name | Type | Description |
|---|---|---|
live_ | prefix | Production transactions, real charges. |
test_ | prefix | Sandbox testing, no real charges. |
The client validates the key format at construction and exposes the detected
mode on client.mode ("live" or "test").
import { VatlyClient } from "@getvatly/sdk";
const vatly = new VatlyClient({
apiKey: process.env.VATLY_API_KEY, // live_… or test_…
});
// Create a checkout
const checkout = await vatly.checkouts.create({
redirectUrlSuccess: "https://yourapp.com/success",
redirectUrlCanceled: "https://yourapp.com/canceled",
products: [{ id: "subscription_plan_abc123", quantity: 1 }],
});
// Redirect the customer to the hosted checkout page
console.log(checkout.links.checkoutUrl.href);
On Node, VATLY_API_KEY is read from process.env as a fallback. On edge
runtimes without process, pass apiKey explicitly.
Idempotency
The SDK automatically attaches an Idempotency-Key header to every POST,
PATCH, and DELETE request (a UUID v4). Checkout creation, subscription
updates, and refund cancellations are protected out of the box, and the key is
reused across automatic retries so a retried call is deduped server-side.
Separate method calls generate separate keys. Reuse an explicit key when your application retries the same operation after an uncertain result.
Override the key per call
Pass idempotencyKey in the request options when you have your own request ID:
await vatly.checkouts.create(body, { idempotencyKey: "checkout-create-123" });
await vatly.subscriptions.update("subscription_123", { quantity: 2 }, {
idempotencyKey: "subscription-update-123",
});
Custom generator or disable auto-generation
// Custom generator (e.g. tie keys to a tracing span)
new VatlyClient({ idempotencyKeyGenerator: () => span.context().traceId });
// Disable entirely — caller must supply opts.idempotencyKey for retries to work
new VatlyClient({ idempotencyKeyGenerator: false });
Retries
GETs and keyed mutations retry 429, 5xx, timeouts, and network failures
with exponential backoff and jitter (default maxRetries: 2), honoring
Retry-After. Keyed 409 errors retry only when
details.idempotency_outcome is in_progress. An unknown outcome requires
reading/reconciling the resource before any further mutation.
Pagination
List endpoints are cursor-paginated. Use list() for a single page or
listAll() to walk every page with for await:
const page = await vatly.orders.list({ limit: 25 });
for await (const order of vatly.orders.listAll({ limit: 100 })) {
// ...
}
Resources
The SDK provides access to all Vatly API resources. The complete method and return-type inventory is in the operation reference.
| Resource | Description |
|---|---|
| Checkouts | Create hosted payment pages |
| Customers | Manage customer records |
| Subscriptions | Recurring billing |
| Subscription Plans | Define subscription products |
| One-Off Products | Single-purchase products |
| Orders | Transaction records |
| Refunds | Process refunds |
| Chargebacks | Handle disputes |
| Webhooks | Endpoint management and real-time event notifications |
Error handling
Every non-2xx response maps to a typed error extending VatlyError.
| Name | Status | Description |
|---|---|---|
VatlyAuthError | 401 | Missing or invalid API key. |
VatlyForbiddenError | 403 | Authenticated but not allowed. |
VatlyNotFoundError | 404 | Resource does not exist. |
VatlyConflictError | 409 | Conflict; inspect .details and .retryAfter. |
VatlyValidationError | 422 | Invalid request; exposes .errors: Record<string, string[]>. |
VatlyRateLimitError | 429 | Rate limited; exposes .retryAfter (seconds). |
VatlyApiError | other | Any other API error. |
VatlyConnectionError / VatlyTimeoutError | — | Network failure / timeout. |
Errors include the request method and URL. Resource and list methods also raise
VatlyApiError for malformed JSON, empty bodies, unexpected 204 responses, or
JSON null. Documented no-content operations accept empty success responses;
other resource fields are not runtime schema-validated.
import { VatlyValidationError } from "@getvatly/sdk";
try {
await vatly.customers.create({ email: "" });
} catch (err) {
if (err instanceof VatlyValidationError) {
console.error(err.errors.email);
} else {
throw err;
}
}
Money
Monetary amounts are Money objects — { value, currency } where value is a
decimal string to preserve precision. Never coerce value to a JavaScript
number. Helpers convert to/from integer minor units:
import { toMinorUnits, fromMinorUnits } from "@getvatly/sdk";
toMinorUnits({ value: "29.00", currency: "EUR" }); // → 2900n
fromMinorUnits(2900n, "EUR"); // → { value: "29.00", currency: "EUR" }
Requirements
- Node 20+, Cloudflare Workers, Vercel Edge, Deno, or Bun
- Platform
fetchand Web Crypto (built in on all supported runtimes)