Skip to content

Entitlements Namespace

Check quotas, features, and entitlements for tenant-scoped operations.

Overview

The entitlements namespace provides the "gatekeeper" function for quota-based actions like adding team members.

const entitlements = authvital.entitlements;

Methods

canPerform()

Check if a quota-based action is allowed. This is the main gatekeeper function.

const check = await authvital.entitlements.canPerform(request, 'seats');

if (!check.allowed) {
  return res.status(403).json({
    error: check.reason,
    currentUsage: check.currentUsage,
    limit: check.limit,
  });
}

// Action allowed - proceed

Parameters:

Parameter Type Required Description
request RequestLike Yes Incoming HTTP request
featureKey string Yes Quota to check (e.g., 'seats')

Return Type:

interface QuotaCheckResult {
  allowed: boolean;
  reason?: string;       // Why it's not allowed
  currentUsage: number;
  limit?: number;        // undefined if unlimited
}

Special Handling for 'seats':

The seats feature key is special - it checks license seat availability:

// Before adding a team member
const check = await authvital.entitlements.canPerform(req, 'seats');

if (!check.allowed) {
  return res.status(402).json({
    error: 'No available seats. Upgrade your subscription to add more team members.',
    seatsUsed: check.currentUsage,
    seatsTotal: check.limit,
  });
}

// Add the member...

decrementUsage()

Decrement usage for a quota (call after removing a resource).

// After removing a team member
const { newUsage } = await authvital.entitlements.decrementUsage(request, 'seats');
console.log(`New usage: ${newUsage}`);

Billing Integration

This method requires billing endpoints to be configured. It's designed for future billing integration.


Complete Example: Seat Management

import { createAuthVital } from '@authvital/sdk/server';
import express from 'express';

const authvital = createAuthVital({ /* config */ });
const app = express();

// Check before inviting
app.post('/api/team/invite', async (req, res) => {
  // 1. Check seat availability
  const seatCheck = await authvital.entitlements.canPerform(req, 'seats');

  if (!seatCheck.allowed) {
    return res.status(402).json({
      error: 'Seat limit reached',
      message: seatCheck.reason,
      currentSeats: seatCheck.currentUsage,
      maxSeats: seatCheck.limit,
      upgradeUrl: '/billing/upgrade',
    });
  }

  // 2. Send invitation
  const invitation = await authvital.invitations.send(req, {
    email: req.body.email,
  });

  res.status(201).json(invitation);
});

// Get seat info for UI
app.get('/api/team/seats', async (req, res) => {
  const check = await authvital.entitlements.canPerform(req, 'seats');

  res.json({
    used: check.currentUsage,
    total: check.limit,
    available: check.limit ? check.limit - check.currentUsage : 'unlimited',
    canAddMore: check.allowed,
  });
});