---
title: Setting Up a SaaS Pricing Matrix with Typed Entitlements
description: End-to-end walkthrough of defining typed billable metrics and attaching them to plan variants to build a complete Free vs Pro feature matrix.
order: 5
---

# Setting Up a SaaS Pricing Matrix with Typed Entitlements

This recipe walks through building a complete pricing matrix using all four metric types. By the end, you'll have a Free and Pro tier with boolean feature flags, seat caps, model access config, and credit-metered API calls.

## Step 1: Create the billable metrics

Define the four metrics that make up your pricing matrix. Each has a type and a sensible default value.

**SSO access (boolean):**

```bash
curl -X POST https://api.quotastack.io/v1/billable-metrics \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: metric-sso" \
  -d '{
    "key": "sso",
    "name": "SSO Access",
    "description": "Single sign-on via SAML/OIDC",
    "type": "boolean",
    "default_value": {"enabled": false}
  }'
```

**Team seats (gauge):**

```bash
curl -X POST https://api.quotastack.io/v1/billable-metrics \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: metric-max-seats" \
  -d '{
    "key": "max_seats",
    "name": "Team Seats",
    "description": "Maximum team members allowed",
    "type": "gauge",
    "default_value": {"cap": 1}
  }'
```

**API calls (metered):**

```bash
curl -X POST https://api.quotastack.io/v1/billable-metrics \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: metric-api-call" \
  -d '{
    "key": "api_call",
    "name": "API Call",
    "description": "One API request to the service"
  }'
```

No `type` needed — defaults to `metered`.

**Model access (static):**

```bash
curl -X POST https://api.quotastack.io/v1/billable-metrics \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: metric-model-access" \
  -d '{
    "key": "model_access",
    "name": "AI Model Access",
    "description": "Which AI models are available",
    "type": "static",
    "default_value": {"config": {"models": []}}
  }'
```

## Step 2: Attach metrics to the Free variant

Assuming you have a plan `plan_01` with a Free variant `var_free`:

```bash
# SSO off
curl -X POST https://api.quotastack.io/v1/plans/plan_01/variants/var_free/entitlements \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: attach-free-sso" \
  -d '{"billable_metric_key": "sso", "value": {"enabled": false}}'

# 5 seats
curl -X POST https://api.quotastack.io/v1/plans/plan_01/variants/var_free/entitlements \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: attach-free-seats" \
  -d '{"billable_metric_key": "max_seats", "value": {"cap": 5}}'

# Basic models only
curl -X POST https://api.quotastack.io/v1/plans/plan_01/variants/var_free/entitlements \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: attach-free-models" \
  -d '{"billable_metric_key": "model_access", "value": {"config": {"models": ["gpt-3.5"]}}}'
```

No attachment needed for `api_call` — it's metered, governed by credit grants and the metering rule.

## Step 3: Attach metrics to the Pro variant

```bash
# SSO on
curl -X POST https://api.quotastack.io/v1/plans/plan_01/variants/var_pro/entitlements \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: attach-pro-sso" \
  -d '{"billable_metric_key": "sso", "value": {"enabled": true}}'

# 50 seats
curl -X POST https://api.quotastack.io/v1/plans/plan_01/variants/var_pro/entitlements \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: attach-pro-seats" \
  -d '{"billable_metric_key": "max_seats", "value": {"cap": 50}}'

# All models
curl -X POST https://api.quotastack.io/v1/plans/plan_01/variants/var_pro/entitlements \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: attach-pro-models" \
  -d '{"billable_metric_key": "model_access", "value": {"config": {"models": ["gpt-4", "claude-sonnet", "gpt-3.5"]}}}'
```

## Step 4: Verify the matrix

List entitlements for each variant to confirm the setup:

```bash
# Free variant
curl https://api.quotastack.io/v1/plans/plan_01/variants/var_free/entitlements \
  -H "X-API-Key: qs_live_..."
```

```json
{
  "data": [
    {"billable_metric_key": "sso", "value": {"enabled": false}, "metric_type": "boolean"},
    {"billable_metric_key": "max_seats", "value": {"cap": 5}, "metric_type": "gauge"},
    {"billable_metric_key": "model_access", "value": {"config": {"models": ["gpt-3.5"]}}, "metric_type": "static"}
  ]
}
```

```bash
# Pro variant
curl https://api.quotastack.io/v1/plans/plan_01/variants/var_pro/entitlements \
  -H "X-API-Key: qs_live_..."
```

```json
{
  "data": [
    {"billable_metric_key": "sso", "value": {"enabled": true}, "metric_type": "boolean"},
    {"billable_metric_key": "max_seats", "value": {"cap": 50}, "metric_type": "gauge"},
    {"billable_metric_key": "model_access", "value": {"config": {"models": ["gpt-4", "claude-sonnet", "gpt-3.5"]}}, "metric_type": "static"}
  ]
}
```

## Step 5: How customers inherit entitlements

When a customer subscribes to the Pro variant, they "have":

- **SSO**: enabled (boolean check)
- **Seats**: up to 50 (gauge check)
- **Models**: GPT-4, Claude Sonnet, GPT-3.5 (static config read)
- **API calls**: as many as their credit balance allows (metered, standard entitlement check)

Your application code reads these values and enforces them:

- At login: check the `sso` entitlement to decide whether to redirect to the SAML provider
- At team invite: check `max_seats` against current team size
- At model selection: read `model_access` config and filter the model picker
- Before each API call: run a standard credit-based entitlement check on `api_call`

## Updating entitlements mid-cycle

If you upgrade Pro from 50 to 100 seats mid-cycle:

```bash
curl -X PATCH https://api.quotastack.io/v1/plans/plan_01/variants/var_pro/entitlements/max_seats \
  -H "X-API-Key: qs_live_..." \
  -H "Content-Type: application/json" \
  -d '{"value": {"cap": 100}}'
```

All customers on the Pro variant immediately inherit the updated cap — no migration, no per-customer update needed.

## Common pitfalls

- **Duplicate attach**: If you try to attach `sso` to the Pro variant a second time, you get a `409`. Use PATCH to update the value, or DELETE then re-attach.
- **Wrong value shape**: Attaching `{"cap": 50}` to a `boolean` metric returns `422`. The value shape must match the metric type.
- **Float caps**: `{"cap": 5.5}` is invalid for gauge metrics. Caps must be non-negative integers.
- **Forgetting defaults**: If you don't attach a metric to a variant, the metric's `default_value` applies. Make sure your defaults make sense for the "no attachment" case.
