Test the product integration system with your subscriptions
Generate a short-lived JWT token to authenticate users into your product
Check if the current user has an active subscription for a product
Authenticate using API keys (for backend operations)
API keys can be generated in the Settings page. Use them to authenticate server-to-server API calls.
How your external product validates the launch token
// In your product (e.g., HR Management Tool) import jwt from 'jsonwebtoken' app.get('/api/auth/portal', async (req, res) => { const { token } = req.query try { // Validate token with shared secret const payload = jwt.verify(token, PORTAL_JWT_SECRET) // Payload contains: // - userId, email, name, role // - companyId, companyName // - subscription tier & features // Create or update user in your system const user = await findOrCreateUser({ email: payload.email, companyId: payload.companyId, role: payload.role, }) // Store subscription info await updateCompanySubscription(payload.companyId, { tier: payload.subscription.tier, features: payload.subscription.features, }) // Create session and redirect req.session.userId = user.id res.redirect('/dashboard') } catch (error) { res.redirect('https://portal.yourdomain.com/subscriptions') } })
Enforce feature limits based on subscription tier
// Middleware to check subscription features async function requireFeature(featureName) { return async (req, res, next) => { const subscription = req.company.subscription if (!subscription.features[featureName]) { return res.status(403).json({ error: `Upgrade to access ${featureName}`, upgradeUrl: 'https://portal.yourdomain.com/pricing' }) } next() } } // Check feature limits async function checkLimit(limitName) { return async (req, res, next) => { const subscription = req.company.subscription const limit = subscription.features[limitName] || 0 const currentCount = await getCurrentUsage(req.company.id, limitName) if (currentCount >= limit) { return res.status(403).json({ error: `Plan limit reached: ${limit} ${limitName}`, current: currentCount, upgradeUrl: 'https://portal.yourdomain.com/pricing' }) } next() } } // Usage app.post('/api/employees', requireFeature('advancedReporting'), checkLimit('maxEmployees'), async (req, res) => { // Create employee... } )
Receive real-time updates when subscriptions change
// Handle portal webhooks in your product import crypto from 'crypto' app.post('/webhooks/portal', async (req, res) => { // Verify signature const signature = req.headers['x-portal-signature'] const body = JSON.stringify(req.body) const expectedSignature = crypto .createHmac('sha256', WEBHOOK_SECRET) .update(body) .digest('hex') if (signature !== expectedSignature) { return res.status(401).json({ error: 'Invalid signature' }) } const { event, data } = req.body switch (event) { case 'subscription.created': case 'subscription.updated': await updateCompanySubscription(data.companyId, { tier: data.tier, features: data.tier.features, status: data.status, expiresAt: data.currentPeriodEnd, }) break case 'subscription.canceled': await disableCompanyAccess(data.companyId) break case 'subscription.renewed': await enableCompanyAccess(data.companyId) break } res.json({ received: true }) })
See the full integration documentation for detailed examples and best practices.