TypeScript SDK
Complete reference for the @slootly/sdk npm package.
Installation
npm install @slootly/sdkInitialization
Simple (API key only)
import { Slootly } from '@slootly/sdk';
const gate = new Slootly('sk_live_your_api_key');Full Configuration
import { Slootly } from '@slootly/sdk';
const gate = new Slootly({
apiKey: 'sk_live_your_api_key',
baseUrl: 'https://api.slootly.dev/v1', // default
cacheTtlMs: 300_000, // 5 minutes, default
enableJwtVerification: true, // default
timeout: 5_000, // 5 seconds, default
checkoutBaseUrl: 'https://pay.slootly.dev', // default
});SlootlyConfig Options
| Property | Type | Default | Description |
|---|---|---|---|
apiKey | string | (required) | API key starting with sk_live_ or sk_test_ |
baseUrl | string | https://api.slootly.dev/v1 | Slootly API base URL |
cacheTtlMs | number | 300000 | In-memory cache TTL in milliseconds |
enableJwtVerification | boolean | true | Enable JWT offline verification |
timeout | number | 5000 | HTTP request timeout in milliseconds |
checkoutBaseUrl | string | https://pay.slootly.dev | Hosted checkout base URL |
fetch | typeof fetch | globalThis.fetch | Custom fetch (for testing or edge runtimes) |
gate.check()
Check subscription status for a user on a platform. This is the primary SDK method. It checks in order: in-memory cache, JWT offline verification, then API call.
const sub = await gate.check(userId: string, platform: Platform): Promise<Subscription>Parameters
| Parameter | Type | Description |
|---|---|---|
userId | string | Platform-specific user ID (e.g., Telegram from.id as string) |
platform | Platform | 'telegram' | 'discord' | 'whatsapp' | 'slack' | 'custom' |
Returns: Subscription
| Property | Type | Description |
|---|---|---|
active | boolean | Whether the user has an active subscription |
plan | string | null | Plan slug (e.g., 'pro'). null if no subscription |
planId | string | null | Plan ID |
status | SubscriptionStatus | 'active' | 'trialing' | 'past_due' | 'canceled' | 'expired' | 'none' |
currentPeriodStart | Date | null | Current billing period start |
currentPeriodEnd | Date | null | Current billing period end |
cancelAtPeriodEnd | boolean | Whether the sub will cancel at period end |
trialEnd | Date | null | Trial end date. null if not on trial |
subscriberId | string | null | Slootly subscriber ID |
platforms | Platform[] | All platforms linked to this subscriber |
metadata | Record<string, unknown> | Developer-defined metadata |
Example
const sub = await gate.check('123456789', 'telegram');
if (sub.active) {
console.log('Plan:', sub.plan); // 'pro'
console.log('Status:', sub.status); // 'active'
console.log('Expires:', sub.currentPeriodEnd);
console.log('Platforms:', sub.platforms); // ['telegram', 'discord']
} else {
console.log('No active subscription');
}gate.checkoutUrl()
Generate a checkout URL for a user to subscribe to a plan. This is a synchronous method -- no API call needed.
const url = gate.checkoutUrl(
userId: string,
planSlug: string,
platform: Platform,
options?: CheckoutOptions
): stringParameters
| Parameter | Type | Description |
|---|---|---|
userId | string | Platform-specific user ID |
planSlug | string | Plan slug (e.g., 'pro') |
platform | Platform | Platform name |
options.successUrl | string? | Custom success redirect URL |
options.cancelUrl | string? | Custom cancel redirect URL |
options.email | string? | Pre-fill customer email |
options.metadata | Record<string, string>? | Additional metadata |
Example
// Simple
const url = gate.checkoutUrl('123456789', 'pro', 'telegram');
// => https://pay.slootly.dev/checkout/pro?uid=123456789&platform=telegram
// With options
const url = gate.checkoutUrl('123456789', 'pro', 'telegram', {
successUrl: 'https://t.me/mybot',
email: 'user@example.com',
metadata: { referral: 'homepage' },
});gate.getPlans()
Fetch all active plans for the project.
const plans = await gate.getPlans(): Promise<Plan[]>Plan Type
| Property | Type | Description |
|---|---|---|
id | string | Plan ID |
name | string | Display name |
slug | string | URL-safe identifier |
description | string | null | Plan description |
amount | number | Price in smallest currency unit (cents) |
currency | string | Currency code (e.g., 'usd') |
interval | BillingInterval | 'day' | 'week' | 'month' | 'year' |
intervalCount | number | Billing interval count |
trialDays | number | Free trial days |
features | string[] | Feature list |
metadata | Record<string, unknown> | Custom metadata |
Example
const plans = await gate.getPlans();
for (const plan of plans) {
console.log(`${plan.name}: $${plan.amount / 100}/${plan.interval}`);
console.log('Features:', plan.features.join(', '));
}gate.cancelSubscription()
Cancel a user's subscription. The subscription remains active until the end of the current billing period.
await gate.cancelSubscription(subscriberId: string): Promise<void>const sub = await gate.check('123456789', 'telegram');
if (sub.subscriberId) {
await gate.cancelSubscription(sub.subscriberId);
// Subscription remains active until sub.currentPeriodEnd
}gate.onEvent()
Create Express/Connect-compatible middleware for receiving Slootly webhooks.
import express from 'express';
const app = express();
app.post('/webhooks/slootly', gate.onEvent((event) => {
switch (event.type) {
case 'subscription.created':
console.log('New subscriber:', event.data.subscriberId);
break;
case 'subscription.canceled':
console.log('Canceled:', event.data.subscriberId);
break;
case 'payment.failed':
console.log('Payment failed:', event.data.subscriberId);
break;
}
}));gate.verifyWebhook()
Manually verify a webhook signature and parse the event.
const event = gate.verifyWebhook(
payload: string, // raw request body
signature: string, // Slootly-Signature header
secret: string // webhook secret (whsec_...)
): WebhookEventconst event = gate.verifyWebhook(
req.body,
req.headers['slootly-signature'],
'whsec_your_webhook_secret'
);
console.log(event.type); // 'subscription.created'
console.log(event.data); // WebhookEventData
console.log(event.createdAt); // DateCache Management
// Clear all cached subscription data
gate.clearCache();
// Clean up SDK resources when shutting down
gate.destroy();Error Handling
import { Slootly, ValidationError } from '@slootly/sdk';
try {
const sub = await gate.check(userId, 'telegram');
} catch (err) {
if (err instanceof ValidationError) {
// Invalid input (empty userId, invalid platform)
console.error('Validation error:', err.message);
} else {
// Network error, auth error, etc.
console.error('Slootly error:', err);
}
}Info
The SDK gracefully handles network failures. If the API is unreachable and a cached JWT is available, the SDK falls back to JWT verification automatically. Your bot continues working even if Slootly is temporarily down.
Type Reference
type Platform = 'telegram' | 'discord' | 'whatsapp' | 'slack' | 'custom';
type SubscriptionStatus = 'active' | 'trialing' | 'past_due'
| 'canceled' | 'expired' | 'none';
type BillingInterval = 'day' | 'week' | 'month' | 'year';
type WebhookEventType =
| 'subscription.created'
| 'subscription.renewed'
| 'subscription.updated'
| 'subscription.canceled'
| 'payment.failed'
| 'test.ping';