@crovver/sdk-node
v1.0.0
Published
Official TypeScript/JavaScript SDK for Crovver
Readme
Crovver SDK
Official TypeScript/JavaScript SDK for integrating Crovver subscription management into your SaaS application.
Features
- Complete API Coverage - All public endpoints implemented
- TypeScript Support - Full type definitions included
- B2B & D2C Support - Works with both organization types
- Error Handling - Built-in error handling with
CrovverErrorclass - Automatic Retries - Configurable retry with exponential backoff for transient failures
- Debug Logging - Optional debug mode for development
- ESM & CommonJS - Dual module support
Installation
npm install crovver-node
# or
yarn add crovver-node
# or
pnpm add crovver-nodeQuick Start
import { CrovverClient } from "crovver-node";
const crovver = new CrovverClient({
apiKey: "your-api-key-here",
baseUrl: "https://your-crovver-instance.com", // Optional
});
// Check if a user can access a feature
const canAccess = await crovver.canAccess("tenant-123", "advanced-analytics");
if (canAccess) {
console.log("Access granted!");
}Configuration
interface CrovverConfig {
apiKey: string; // Your organization's API key (required)
baseUrl?: string; // Crovver instance URL (default: http://localhost:3000)
timeout?: number; // Request timeout in ms (default: 30000)
maxRetries?: number; // Max retries for failed requests (default: 3)
debug?: boolean; // Enable debug logging (default: false)
logger?: (message: string, data?: unknown) => void; // Custom logger
}Error Handling
import { CrovverClient, CrovverError } from "crovver-node";
try {
await crovver.canAccess("tenant-123", "premium-feature");
} catch (error) {
if (error instanceof CrovverError) {
console.error("Error:", error.message);
console.error("Status Code:", error.statusCode);
console.error("Is Retryable:", error.isRetryable);
}
}Automatic Retries:
The SDK automatically retries failed requests for:
- 5xx server errors
- 429 rate limit errors
- Network timeouts
Client errors (400, 401, 403, 404) are NOT retried.
API Reference
Tenant Management (B2B Only)
createTenant
Create a new tenant/workspace. B2B organizations only - D2C tenants are created automatically during checkout.
const result = await crovver.createTenant({
externalTenantId: "company-123",
name: "Acme Corporation",
ownerExternalUserId: "user-456",
ownerEmail: "[email protected]",
ownerName: "John Doe",
});
console.log("Tenant ID:", result.tenant.id);getTenant
const { tenant, members } = await crovver.getTenant("company-123");Plans
getPlans
Fetch all available plans for your organization.
const { plans, organization } = await crovver.getPlans();
plans.forEach((plan) => {
console.log(
`${plan.name}: ${plan.pricing.currency} ${plan.pricing.amount}/${plan.pricing.interval}`,
);
});Subscriptions
getSubscriptions
Get active subscriptions for a tenant (B2B) or user (D2C).
const { subscriptions, tenant } = await crovver.getSubscriptions("company-123");
subscriptions.forEach((sub) => {
console.log(`Plan: ${sub.plan.name}, Status: ${sub.status}`);
});Checkout
createCheckoutSession
Create a payment checkout session.
B2B:
const checkout = await crovver.createCheckoutSession({
requestingUserId: "user-456",
requestingTenantId: "company-123",
planId: "plan-uuid",
provider: "stripe",
successUrl: "https://myapp.com/success",
cancelUrl: "https://myapp.com/cancel",
});
window.location.href = checkout.checkoutUrl;D2C:
const checkout = await crovver.createCheckoutSession({
requestingUserId: "user-789",
userEmail: "[email protected]",
userName: "John Doe",
planId: "plan-uuid",
provider: "stripe",
successUrl: "https://myapp.com/success",
cancelUrl: "https://myapp.com/cancel",
});Entitlement Checks
canAccess
Check if a tenant/user has access to a feature.
const canAccess = await crovver.canAccess("company-123", "advanced-analytics");recordUsage
Record usage for metered features.
await crovver.recordUsage("company-123", "api-calls", 1, {
endpoint: "/api/v1/users",
});checkUsageLimit
Check usage against limits.
const usage = await crovver.checkUsageLimit("company-123", "api-calls");
console.log(`Used: ${usage.current} / ${usage.limit}`);
console.log(`Remaining: ${usage.remaining}`);
if (!usage.allowed) {
console.log("Usage limit reached!");
}Seat-Based Billing
For plans with seat-based pricing.
getActiveCapacity
const capacity = await crovver.getActiveCapacity("company-123");
console.log(`Active seats: ${capacity.activeCount}/${capacity.capacityUnits}`);
console.log(`Utilization: ${capacity.utilizationPercentage}%`);recordSeatAllocation
Record when a user is added to a tenant.
const result = await crovver.recordSeatAllocation({
tenantId: "company-123",
externalUserId: "user-789",
email: "[email protected]",
name: "Jane Doe",
});
if (result.requiresCheckout) {
// Need to upgrade capacity
console.log(`Proration amount: $${result.prorationAmount}`);
const checkout = await crovver.createProrationCheckout({
tenantId: "company-123",
newCapacity: result.newCapacity!,
prorationAmount: result.prorationAmount!,
successUrl: "https://myapp.com/success",
cancelUrl: "https://myapp.com/cancel",
});
window.location.href = checkout.checkoutUrl!;
} else {
console.log("User added successfully");
}removeSeat
Remove a user's seat. Price decreases in next billing cycle.
const result = await crovver.removeSeat({
tenantId: "company-123",
externalUserId: "user-789",
});createProrationCheckout
Create checkout for seat upgrades.
const checkout = await crovver.createProrationCheckout({
tenantId: "company-123",
newCapacity: 11,
prorationAmount: 25.5,
successUrl: "https://myapp.com/success",
cancelUrl: "https://myapp.com/cancel",
});Payment Providers
getSupportedProviders
const { providers } = await crovver.getSupportedProviders();
providers.forEach((p) => console.log(`${p.name}: ${p.code}`));TypeScript Types
All types are exported for use:
import {
CrovverClient,
CrovverError,
CrovverConfig,
Plan,
Subscription,
Tenant,
CreateTenantRequest,
CreateCheckoutSessionRequest,
CheckUsageLimitResponse,
RecordSeatAllocationResponse,
// ... and more
} from "crovver-node";License
MIT
