Typed client for the Sellub commerce platform.
Sibling of @duabalabs/dps-client. Where DPS handles tenant
identity / automation, Sellub handles commerce — catalog, checkout, orders,
fulfillment, payments. This package wraps Sellub's REST + (later) GraphQL
surfaces with typed helpers.
The ShopClient is a thin GraphQL wrapper around Sellub's Vendure Shop API
at ${baseUrl}/shop-api. It manages session continuity for you (Vendure's
vendure-auth-token is captured from response headers and re-attached on
the next request).
import { createSellubClient } from "@duabalabs/sellub-client";
const sellub = createSellubClient({
baseUrl: process.env.NEXT_PUBLIC_SELLUB_API_URL, // default https://api.sellub.com
publishableKey: process.env.NEXT_PUBLIC_SELLUB_PUBLISHABLE_KEY,
channelToken: process.env.NEXT_PUBLIC_SELLUB_CHANNEL_TOKEN, // for Shop
});
const products = await sellub.shop.getProducts({ take: 12, term: "shoes" });
const order = await sellub.shop.addItemToOrder({
productVariantId: products.items[0].id,
quantity: 1,
});
await sellub.shop.setCustomerForOrder({
emailAddress: "buyer@example.com",
firstName: "Buyer",
lastName: "Co",
});
await sellub.shop.transitionOrderToState({ state: "ArrangingPayment" });
const paid = await sellub.shop.addPaymentToOrder({ method: "paystack" });For Shop-only callers, createShopClient(...) is exported directly. See the
CHANGELOG for the full surface.
Three surfaces today, all hitting api.sellub.com/external-payments/* and
authenticating with a publishable key (X-Sellub-Publishable-Key):
externalPayments— one-off payments routed to a seller's Paystack subaccount (donations, simple buy buttons, embedded checkout).subscriptions— recurring billing on Paystack plans.invoices— hosted Paystack payment requests on behalf of a seller.
const sellub = createSellubClient({
baseUrl: process.env.NEXT_PUBLIC_SELLUB_API_URL, // default: https://api.sellub.com
publishableKey: process.env.NEXT_PUBLIC_SELLUB_PUBLISHABLE_KEY,
});const init = await sellub.externalPayments.initialize({
channelSlug: "duabanti",
email: "donor@example.com",
amount: 5000, // pesewas — GHS 50.00
customerName: "Kwame Mensah",
description: "Donation to DuabaNti",
callbackUrl: "https://duabanti.org/donate/thank-you",
metadata: { source: "donate-modal" },
});
if (init.success && init.authorizationUrl) {
window.location.href = init.authorizationUrl;
}After Paystack redirects back, verify on your callback page:
const result = await sellub.externalPayments.verify(reference);
if (result.success && result.status === "success") {
// unlock whatever the payment was for
}const sub = await sellub.subscriptions.start({
channelSlug: "duabaconnect",
email: "tenant@example.com",
customerName: "Acme Ltd",
plan: {
name: "DuabaConnect Pro / monthly",
amount: 15000, // GHS 150.00
interval: "monthly",
currency: "GHS",
},
callbackUrl: "https://app.duabaconnect.com/billing/return",
metadata: { tenantId: "acme" },
});
if (sub.success && sub.authorizationUrl) {
window.location.href = sub.authorizationUrl;
}Check status / cancel:
const status = await sellub.subscriptions.status(subscriptionCode);
await sellub.subscriptions.cancel({
channelSlug: "duabaconnect",
subscriptionCode,
emailToken,
});const inv = await sellub.invoices.create({
channelSlug: "duabatrade",
email: "buyer@example.com",
customerName: "Buyer Co.",
currency: "GHS",
dueDate: "2025-12-31",
description: "Order #1234",
lineItems: [
{ name: "Logistics", amount: 25000, quantity: 1 },
{ name: "Insurance", amount: 5000, quantity: 1 },
],
sendNotification: true,
});
if (inv.success && inv.hostedUrl) {
// share inv.hostedUrl with the buyer
}
const fetched = await sellub.invoices.get(inv.requestCode!);| Version | Surface | Purpose |
|---|---|---|
| 0.1 | externalPayments |
one-off payments (donations, simple buttons) |
| 0.3 | + subscriptions, invoices |
recurring billing + hosted invoices |
| 0.4 | + ShopClient |
Vendure Shop GraphQL — catalog, cart, checkout, orders |
| 0.5 | AdminClient |
Vendure Admin GraphQL — provisioning, fulfillment, reports |
| 0.6 | EmbedTokens |
short-lived session tokens for the iframe admin embed |
| 0.7 | Webhooks |
HMAC verifier + typed payloads for inbound Sellub webhooks |
MIT