> ## Documentation Index
> Fetch the complete documentation index at: https://autumn-b9b4c0fb-dev.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Entity-level balances

> Grant usage limits per entity, such as 50 credits per user per month

Entities are a resource that lives under a parent customer, that can have it's own plans and feature balances.

Entity-level balances let you set usage limits that apply to each entity (like users, workspaces, or projects) individually. Instead of a single shared pool, each entity gets their own balance.

You model this with a **license plan**: a plan describing everything one entity gets. The parent plan offers a pool of those licenses, and you assign a license to an entity to give it its own balance.

This is useful when you want to ensure fair usage across team members or isolate resource consumption per workspace.

<Note>
  For the mechanics behind this and the other way to provision entity plans, see [entity plans](/documentation/modelling-pricing/entity-plans). If you only need to charge by headcount, with no per-seat limits, see [per-seat pricing](/examples/per-seat) instead.
</Note>

## Example case

We have an AI meeting notes product with team-based pricing:

* **Team plan**: \$30 per seat per month
* **Each seat gets**: 50 meeting summaries per month

If a team has 8 users, they pay \$30 \times 8 = \$240/month, and each user gets their own 50 summaries.

## Configure Pricing

<Steps>
  <Step>
    #### Create Features

    Create two features:

    1. **Seats** - A `metered` `non-consumable` feature identifying the entity type (team members)
    2. **Meeting Summaries** - A `metered` `consumable` feature for the number of meeting summaries generated
  </Step>

  <Step>
    #### Create the Seat License Plan

    Create a **Seat** plan holding everything one team member gets:

    1. A **\$30/month price**
    2. **Meeting Summaries**: 50 per month

    Give it its own group. Attaching a plan replaces other plans in the same group, so a license plan sharing a group with its parent would knock the parent off.
  </Step>

  <Step>
    #### Create Team Plan

    Create a Team plan and, under **Licenses**, add the Seat plan with **0 included** seats.

    The Team plan now offers a pool of Seat licenses at \$30/month each. (Set **included** above 0 to give the plan some free seats.) A team member only receives their own 50 summaries once a license is assigned to them.
  </Step>
</Steps>

## Implementation

<Steps>
  <Step>
    #### Create an Autumn Customer

    When an organization signs up, create an Autumn customer.

    <CodeGroup>
      ```typescript Node.js theme={null}
      import { Autumn } from "autumn-js";

      const autumn = new Autumn({
        secretKey: 'am_sk_42424242',
      });

      const { data, error } = await autumn.customers.create({
        id: "org_123",
        name: "Acme Corp",
        email: "admin@acme.com",
      });
      ```

      ```python Python theme={null}
      import asyncio
      from autumn import Autumn

      autumn = Autumn('am_sk_42424242')

      async def main():
          customer = await autumn.customers.create(
              id="org_123",
              name="Acme Corp",
              email="admin@acme.com",
          )

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      curl --request POST \
        --url https://api.useautumn.com/v1/customers \
        --header 'Authorization: Bearer am_sk_42424242' \
        --header 'Content-Type: application/json' \
        --data '{
          "id": "org_123",
          "name": "Acme Corp",
          "email": "admin@acme.com"
        }'
      ```
    </CodeGroup>
  </Step>

  <Step>
    #### Create Initial Entity

    Create an entity for the admin user who is signing up. This just registers the entity — no balance is granted until a license is assigned to it. This should be done server-side for security.

    <CodeGroup>
      ```typescript Node.js theme={null}
      import { Autumn } from "autumn-js";

      const autumn = new Autumn({
        secretKey: 'am_sk_42424242',
      });

      // Create entity for the initial admin user
      await autumn.entities.create("org_123", {
        id: "user_admin",
        name: "Admin User",
        feature_id: "seats",
      });
      ```

      ```python Python theme={null}
      import asyncio
      from autumn import Autumn

      autumn = Autumn("am_sk_42424242")

      async def main():
          # Create entity for the initial admin user
          await autumn.features.create_entity(
              customer_id="org_123",
              id="user_admin",
              name="Admin User",
              feature_id="seats",
          )

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      curl -X POST "https://api.useautumn.com/v1/customers/org_123/entities" \
        -H "Authorization: Bearer am_sk_42424242" \
        -H "Content-Type: application/json" \
        -d '{
          "id": "user_admin",
          "name": "Admin User",
          "feature_id": "seats"
        }'
      ```
    </CodeGroup>

    <Note>
      This entity exists but has no balances yet. It receives its 50 meeting summaries once you assign it a Seat license, a couple of steps below.
    </Note>
  </Step>

  <Step>
    #### Attach the Team Plan and Buy Seats

    When the customer upgrades to Team, attach the plan. Pass `licenseQuantities` to say how many Seat licenses they want — `quantity` is the **total** number of seats, including any the plan includes for free.

    <CodeGroup>
      ```typescript Node.js theme={null}
      import { Autumn } from "autumn-js";

      const autumn = new Autumn({
        secretKey: 'am_sk_42424242',
      });

      // 4 seats at $30/month = $120/month
      const { data } = await autumn.billing.attach({
        customerId: "org_123",
        planId: "team",
        licenseQuantities: [{
          licensePlanId: "seat_license",
          quantity: 4,
        }],
      });

      if (data.paymentUrl) {
        // Redirect to Stripe checkout
      }
      ```

      ```python Python theme={null}
      import asyncio
      from autumn import Autumn

      autumn = Autumn("am_sk_42424242")

      async def main():
          # 4 seats at $30/month = $120/month
          response = await autumn.billing.attach(
              customer_id="org_123",
              plan_id="team",
              license_quantities=[{
                  "license_plan_id": "seat_license",
                  "quantity": 4,
              }],
          )

          if response.payment_url:
              # Redirect to Stripe checkout
              pass

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      curl -X POST "https://api.useautumn.com/v1/billing.attach" \
        -H "Authorization: Bearer am_sk_42424242" \
        -H "Content-Type: application/json" \
        -d '{
          "customer_id": "org_123",
          "plan_id": "team",
          "license_quantities": [
            { "license_plan_id": "seat_license", "quantity": 4 }
          ]
        }'
      ```
    </CodeGroup>

    <Note>
      Change the seat count later by attaching again with a new `quantity`. Autumn prorates the difference.
    </Note>
  </Step>

  <Step>
    #### Assign Seat Licenses

    When team members are added, assign each of them a Seat license. This is what gives them their own balance of 50 summaries. It consumes one seat from the pool bought in the previous step.

    <CodeGroup>
      ```typescript Node.js theme={null}
      import { Autumn } from "autumn-js";

      const autumn = new Autumn({
        secretKey: 'am_sk_42424242',
      });

      // Assign a seat to each team member
      await autumn.licenses.attach({
        customerId: "org_123",
        planId: "seat_license",
        entities: [
          { entityId: "user_alice", name: "Alice Smith", featureId: "seats" },
          { entityId: "user_bob", name: "Bob Jones", featureId: "seats" },
          { entityId: "user_charlie", name: "Charlie Brown", featureId: "seats" },
        ],
      });
      ```

      ```python Python theme={null}
      import asyncio
      from autumn import Autumn

      autumn = Autumn("am_sk_42424242")

      async def main():
          # Assign a seat to each team member
          await autumn.licenses.attach(
              customer_id="org_123",
              plan_id="seat_license",
              entities=[
                  {"entity_id": "user_alice", "name": "Alice Smith", "feature_id": "seats"},
                  {"entity_id": "user_bob", "name": "Bob Jones", "feature_id": "seats"},
                  {"entity_id": "user_charlie", "name": "Charlie Brown", "feature_id": "seats"},
              ],
          )

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      curl -X POST "https://api.useautumn.com/v1/licenses.attach" \
        -H "Authorization: Bearer am_sk_42424242" \
        -H "Content-Type: application/json" \
        -d '{
          "customer_id": "org_123",
          "plan_id": "seat_license",
          "entities": [
            { "entity_id": "user_alice", "name": "Alice Smith", "feature_id": "seats" },
            { "entity_id": "user_bob", "name": "Bob Jones", "feature_id": "seats" },
            { "entity_id": "user_charlie", "name": "Charlie Brown", "feature_id": "seats" }
          ]
        }'
      ```
    </CodeGroup>

    <Note>
      `feature_id` is only required when the entity doesn't exist yet — Autumn creates it for you, so you can skip the separate entity-create call.

      Assignment is idempotent: re-assigning someone who already holds an active Seat license succeeds without consuming another seat. If the pool has no seats left, the call errors — buy more seats first.

      After assigning, navigate to the Autumn customer page and you will see the entity and its balance.
    </Note>
  </Step>

  <Step>
    #### Check Access Per Entity

    Before generating a meeting summary, check if that specific user has remaining balance.

    <CodeGroup>
      ```typescript Node.js theme={null}
      import { Autumn } from "autumn-js";

      const autumn = new Autumn({
        secretKey: 'am_sk_42424242',
      });

      // Check Alice's individual balance
      const { data } = await autumn.check({
        customer_id: "org_123",
        feature_id: "meeting_summaries",
        entity_id: "user_alice",
      });

      if (!data.allowed) {
        console.log("Alice has used all her meeting summaries");
      } else {
        console.log(`Alice has ${data.balance} summaries remaining`);
      }
      ```

      ```python Python theme={null}
      import asyncio
      from autumn import Autumn

      autumn = Autumn("am_sk_42424242")

      async def main():
          # Check Alice's individual balance
          response = await autumn.check(
              customer_id="org_123",
              feature_id="meeting_summaries",
              entity_id="user_alice",
          )
          
          if not response.allowed:
              print("Alice has used all her meeting summaries")
          else:
              print(f"Alice has {response.balance} summaries remaining")

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      curl -X POST "https://api.useautumn.com/v1/check" \
        -H "Authorization: Bearer am_sk_42424242" \
        -H "Content-Type: application/json" \
        -d '{
          "customer_id": "org_123",
          "feature_id": "meeting_summaries",
          "entity_id": "user_alice"
        }'
      ```
    </CodeGroup>

    <Expandable title="check response (entity-level)">
      ```json theme={null}
      {
        "allowed": true,
        "customer_id": "org_123",
        "feature_id": "meeting_summaries",
        "entity_id": "user_alice",
        "balance": 47,
        "usage": 3,
        "included_usage": 50,
        "unlimited": false
      }
      ```
    </Expandable>
  </Step>

  <Step>
    #### Track Usage Per Entity

    When a user generates a summary, track the usage against their entity.

    <CodeGroup>
      ```typescript Node.js theme={null}
      import { Autumn } from "autumn-js";

      const autumn = new Autumn({
        secretKey: 'am_sk_42424242',
      });

      // Track usage for Alice
      await autumn.track({
        customer_id: "org_123",
        feature_id: "meeting_summaries",
        entity_id: "user_alice",
        value: 1,
      });
      ```

      ```python Python theme={null}
      import asyncio
      from autumn import Autumn

      autumn = Autumn("am_sk_42424242")

      async def main():
          # Track usage for Alice
          await autumn.track(
              customer_id="org_123",
              feature_id="meeting_summaries",
              entity_id="user_alice",
              value=1,
          )

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      curl -X POST "https://api.useautumn.com/v1/track" \
        -H "Authorization: Bearer am_sk_42424242" \
        -H "Content-Type: application/json" \
        -d '{
          "customer_id": "org_123",
          "feature_id": "meeting_summaries",
          "entity_id": "user_alice",
          "value": 1
        }'
      ```
    </CodeGroup>
  </Step>

  <Step>
    #### Check Customer-level Balance (Optional)

    You can also check the total balance across all entities, useful for admin dashboards.

    <CodeGroup>
      ```typescript Node.js theme={null}
      import { Autumn } from "autumn-js";

      const autumn = new Autumn({
        secretKey: 'am_sk_42424242',
      });

      // Check total balance across all users (omit entity_id)
      const { data } = await autumn.check({
        customer_id: "org_123",
        feature_id: "meeting_summaries",
      });

      // With 3 users at 50 each = 150 total
      console.log(`Team has ${data.balance} total summaries remaining`);
      ```

      ```python Python theme={null}
      import asyncio
      from autumn import Autumn

      autumn = Autumn("am_sk_42424242")

      async def main():
          # Check total balance across all users
          response = await autumn.check(
              customer_id="org_123",
              feature_id="meeting_summaries",
          )
          
          print(f"Team has {response.balance} total summaries remaining")

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      curl -X POST "https://api.useautumn.com/v1/check" \
        -H "Authorization: Bearer am_sk_42424242" \
        -H "Content-Type: application/json" \
        -d '{
          "customer_id": "org_123",
          "feature_id": "meeting_summaries"
        }'
      ```
    </CodeGroup>

    <Expandable title="check response (customer-level)">
      ```json theme={null}
      {
        "allowed": true,
        "customer_id": "org_123",
        "feature_id": "meeting_summaries",
        "balance": 141,
        "usage": 9,
        "included_usage": 150,
        "unlimited": false
      }
      ```

      The total is the sum of all entity balances (3 users × 50 = 150 included).
    </Expandable>
  </Step>

  <Step>
    #### Release Seat Licenses

    When a team member leaves, release their license. Their balance is removed and the seat returns to the pool, ready to be assigned to someone else.

    <CodeGroup>
      ```typescript Node.js theme={null}
      import { Autumn } from "autumn-js";

      const autumn = new Autumn({
        secretKey: 'am_sk_42424242',
      });

      // Free up Bob's seat
      await autumn.licenses.release({
        customerId: "org_123",
        licensePlanId: "seat_license",
        entityIds: ["user_bob"],
      });
      ```

      ```python Python theme={null}
      import asyncio
      from autumn import Autumn

      autumn = Autumn("am_sk_42424242")

      async def main():
          # Free up Bob's seat
          await autumn.licenses.release(
              customer_id="org_123",
              license_plan_id="seat_license",
              entity_ids=["user_bob"],
          )

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      curl -X POST "https://api.useautumn.com/v1/licenses.release" \
        -H "Authorization: Bearer am_sk_42424242" \
        -H "Content-Type: application/json" \
        -d '{
          "customer_id": "org_123",
          "license_plan_id": "seat_license",
          "entity_ids": ["user_bob"]
        }'
      ```
    </CodeGroup>

    <Note>
      Releasing a license frees the seat but does not change what the customer pays — they keep the 4 seats they bought. To stop paying for a seat, attach the Team plan again with a lower `quantity`; Autumn prorates the refund.

      `license_plan_id` is optional, and only needed to disambiguate when an entity holds licenses from more than one plan.
    </Note>
  </Step>
</Steps>

## Summary

| Level              | Check/Track With          | Use Case                            |
| ------------------ | ------------------------- | ----------------------------------- |
| **Entity-level**   | `entity_id: "user_alice"` | Individual user limits, fair usage  |
| **Customer-level** | No `entity_id`            | Admin dashboards, total consumption |

Entity-level balances are ideal when you want to:

* Ensure fair usage across team members
* Isolate consumption per workspace or project
* Bill per-entity while providing entity-specific limits

To see how many seats a customer has bought and used, call [`licenses.list`](/api-reference/licenses/listLicenses). To see who currently holds one, call [`licenses.list_assignments`](/api-reference/licenses/listLicenseAssignments).
