Seat-based Pricing

This guide shows how to implement seat-based pricing, including per-seat usage metering and per-seat credits that roll up at billing.

What you’ll build:

  • Seat-based plan with per-seat charges (prorated for mid-cycle adds)
  • Per-seat usage metering via events
  • Plan-scoped usage credits that are granted to each seat and applied on invoices
  • Feature gating that respects per-seat credits and usage

Important notes:

  • Prepaid top-up credits (customer buys a pack and draws down) are not supported yet.
  • Seat additions are billed immediately by default and prorated for the remaining period.

1) Configure a seat-based plan (UI)

In Plans → Create:

  1. Add a fixed component (optional) for a base fee.
  2. Add a per-unit component for seats, set the per-seat price, and keep bill-immediately enabled (default) to charge new seats mid-cycle with proration.
  3. If you also need per-seat usage (e.g., API calls per user), add a usage component tied to a metric (event name) you’ll send from your app.

Tip: You can configure a minimum seat count on the per-unit component. Billing will charge at least the minimum each cycle.

2) Manage seats via API

Add a seat for an organization (or fallback to the billing user). This creates/links a seat customer and copies plan features to them. It also grants plan-scoped credits to the seat if configured.

Add seat:

curl -X POST "https://api.getlumen.dev/v1/seats/add" \
  -H "Authorization: Bearer $LUMEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "organization_id": "org_123",
    "created_user_id": "user_ext_456",
    "created_user_info": {
      "name": "Jane Doe",
      "email": "jane@example.com"
    },
    "idempotency_key": "seat_add_org123_user456"
  }'

Remove seat:

curl -X POST "https://api.getlumen.dev/v1/seats/remove" \
  -H "Authorization: Bearer $LUMEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "organization_id": "org_123",
    "removed_user_id": "user_ext_456"
  }'

Notes:

  • Provide either organization_id or user_id (fallback) for the billing customer context.
  • Seat adds emit a seat_added event and create a seat customer record if it doesn’t exist.
  • Seat removes revoke that seat’s active grants for the current plan.

Related API: see “Seats API”.

3) Grant per-seat usage credits (plan-scoped)

Create a plan-scoped usage credit definition. When you add seats, each seat customer automatically receives a grant based on matching plan definitions. Set billingVisible: true if you want credit application to appear as negative line items on invoices.

Example: 1,000 API calls per seat per month for a specific usage component.

curl -X POST "https://api.getlumen.dev/v1/credits/definitions" \
  -H "Authorization: Bearer $LUMEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "plan",
    "applicationType": "usage",
    "planId": "plan_abc",
    "priceId": "price_123",
    "priceComponentId": "comp_usage_xyz",
    "name": "Per-seat API credits",
    "billingVisible": true,
    "defaultAmount": 1000,
    "refillAmount": 1000,
    "renewOnBilling": true
  }'

Behavior:

  • At billing, usage for each seat is computed for the usage component.
  • Billing-visible usage credits for each seat are converted to monetary value (unit price × credits used) and added as negative line items.
  • Credits and usage are rolled up across seats on the invoice.

4) Meter per-seat usage from your backend

Send events with the seat user’s external ID as userId. The event name should match the metric configured on your usage component.

import { sendEvent } from "@getlumen/server";

// Count one API call for seat user user_ext_456
await sendEvent({
  name: "api-calls",      // metric/event name configured in the plan
  value: 1,
  userId: "user_ext_456", // external user ID used when the seat was added
});

5) Gate features per seat (credits-aware)

Check entitlements with the seat user’s external ID. For numeric features, the entitlement engine considers both plan features and credits, along with current usage.

import { isFeatureEntitled } from "@getlumen/server";

const allowed = await isFeatureEntitled({
  userId: "user_ext_456",
  feature: "api-calls",
});

if (!allowed) {
  // Show upgrade or enforce a soft limit
}

If you need detailed counters for UI (e.g., remaining credits), use the Entitlements API to fetch usages and creditInfo.

6) Billing behavior you can rely on

  • Seat additions are billed immediately by default and prorated using the remaining period days.
  • For seat-based plans, billing aggregates all members of the organization to compute usage and apply credits.
  • Usage credits that are marked billing-visible appear as line items; monetary credits apply after charges via the credit waterfall.
  • Seats API: /v1/seats (add/remove)
  • Credits API: /v1/credits/definitions, /v1/credits/grants
  • Entitlements API: /v1/entitlements/:customerId