A simplified, type-safe TypeScript wrapper for the Clover APIs
Charges, refunds, customers, and edge-ready webhooks — no SDK dependency.
Clover has no first-class Node SDK, so this library talks to Clover over a small typed fetch-based client — zero runtime dependencies. It gives you a service-oriented client, a typed error hierarchy, money helpers, and framework-ready webhook handling. Part of the same family as @bates-solutions/squareup and @bates-solutions/stripe, so if you know one, you know this.
It targets both Clover hosts transparently:
- Ecommerce API (
scl.clover.com) — Stripe-shaped/v1/...charges, refunds, tokens. - Platform API (
api.clover.com) —/v3/merchants/{mId}/...customers, orders, inventory.
- Zero dependencies – A tiny
fetchclient; no vendor SDK - Type-Safe – Full TypeScript types for inputs and results
- Typed Errors –
parseCloverErrornormalizes HTTP failures into a small class hierarchy - Edge-ready webhooks – WebCrypto signature verification that runs on Node, Deno, Bun, and Workers, plus Express and Lambda adapters, and the Clover URL-verification handshake handled for you
| Dependency | Version |
|---|---|
| Node.js | 22+ (or any runtime with fetch + WebCrypto) |
| TypeScript | 5.0+ |
This package is published on JSR.
# npm / pnpm / yarn (via JSR's npm compatibility)
npx jsr add @bates-solutions/clover
# Deno
deno add jsr:@bates-solutions/cloverDeno / edge runtimes (e.g. Supabase Edge Functions) can import directly:
import { createCloverClient } from 'jsr:@bates-solutions/clover';
import { createWebhookHandler } from 'jsr:@bates-solutions/clover/server';import { createCloverClient } from '@bates-solutions/clover';
const clover = createCloverClient({
apiToken: process.env.CLOVER_API_TOKEN!,
merchantId: process.env.CLOVER_MERCHANT_ID, // required for customers
environment: 'sandbox',
});
// Charge a tokenized card (amount in cents)
const charge = await clover.payments.create({
amount: 1000, // $10.00
currency: 'usd',
source: 'clv_1TSTStok...',
});
// Refund it
const refund = await clover.refunds.create({ chargeId: charge.id! });
// Manage a customer (Platform API — needs merchantId)
const customer = await clover.customers.create({
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com',
});Signature verification uses WebCrypto, so createWebhookHandler runs on any Fetch-API runtime. The initial Clover URL-verification handshake is answered automatically.
// Supabase Edge Function / Deno
import { createWebhookHandler } from '@bates-solutions/clover/server';
const handler = createWebhookHandler({
signingSecret: Deno.env.get('CLOVER_WEBHOOK_SECRET')!,
handlers: {
CHARGE: async (event) => {
console.log('Charge event:', event);
},
},
});
Deno.serve(handler);import express from 'express';
import { createExpressWebhookHandler } from '@bates-solutions/clover/server';
const app = express();
app.use('/webhooks/clover', express.raw({ type: 'application/json' }));
app.post(
'/webhooks/clover',
createExpressWebhookHandler({
signingSecret: process.env.CLOVER_WEBHOOK_SECRET!,
handlers: {
CHARGE: async (event) => {
console.log('Charge event:', event);
},
},
})
);| Service | API | Description |
|---|---|---|
payments |
Ecommerce | Create/get/capture charges |
refunds |
Ecommerce | Create and get refunds |
customers |
Platform | Customer CRUD (/v3/merchants/{mId}) |
import { toCents, fromCents, formatMoney } from '@bates-solutions/clover';
toCents(10.99); // 1099
fromCents(1099); // 10.99
formatMoney(1099, 'usd'); // "$10.99"We welcome contributions! Please see our Contributing Guide for details.
MIT - see LICENSE for details.