> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useautumn.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Track Token Usage

> Records AI token usage for a customer and returns the updated AI credit balance.

Use this after an LLM request when you have input and output token counts. Autumn converts token usage to a dollar amount using the configured model pricing and markup, then tracks that value against the customer's AI credit system.

export const DynamicResponseExample = ({json, statusCode = "200"}) => {
  const toCamelCase = str => {
    return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
  };
  const convertKeysToCamelCase = obj => {
    if (Array.isArray(obj)) {
      return obj.map(item => convertKeysToCamelCase(item));
    }
    if (obj !== null && typeof obj === "object") {
      return Object.keys(obj).reduce((acc, key) => {
        const camelKey = toCamelCase(key);
        acc[camelKey] = convertKeysToCamelCase(obj[key]);
        return acc;
      }, {});
    }
    return obj;
  };
  const [isTypeScript, setIsTypeScript] = useState(() => {
    if (typeof window !== "undefined") {
      try {
        const lang = localStorage.getItem("code");
        return JSON.parse(lang) === "typescript";
      } catch {
        return true;
      }
    }
    return true;
  });
  useEffect(() => {
    const onMintlifyStorage = event => {
      if (event.detail?.key === "code") {
        try {
          const value = JSON.parse(event.detail.value);
          setIsTypeScript(value === "typescript");
        } catch {}
      }
    };
    const pollInterval = setInterval(() => {
      try {
        const lang = localStorage.getItem("code");
        const value = JSON.parse(lang);
        setIsTypeScript(value === "typescript");
      } catch {}
    }, 300);
    document.addEventListener("mintlify-localstorage", onMintlifyStorage);
    return () => {
      document.removeEventListener("mintlify-localstorage", onMintlifyStorage);
      clearInterval(pollInterval);
    };
  }, []);
  const camelCaseJson = useMemo(() => convertKeysToCamelCase(json), [json]);
  const snakeCaseString = JSON.stringify(json, null, 2);
  const camelCaseString = JSON.stringify(camelCaseJson, null, 2);
  return <ResponseExample>
			{isTypeScript ? <CodeBlock language="json" filename={statusCode}>
					{camelCaseString}
				</CodeBlock> : <CodeBlock language="json" filename={statusCode}>
					{snakeCaseString}
				</CodeBlock>}
		</ResponseExample>;
};

export const DynamicResponseField = ({children, name, ...props}) => {
  const convertToCamelCase = str => {
    if (typeof str !== "string") return str;
    return str.replace(/[_-](\w)/g, (_, c) => c.toUpperCase());
  };
  const [lang, setLang] = useState(() => {
    if (typeof window !== "undefined") {
      const stored = localStorage.getItem("code");
      return stored || '"typescript"';
    }
    return '"typescript"';
  });
  useEffect(() => {
    const onMintlifyStorage = event => {
      const key = event.detail?.key;
      if (key === "code") {
        setLang(event.detail.value);
      }
    };
    const pollInterval = setInterval(() => {
      const current = localStorage.getItem("code");
      if (current && current !== lang) {
        setLang(current);
      }
    }, 500);
    document.addEventListener("mintlify-localstorage", onMintlifyStorage);
    return () => {
      document.removeEventListener("mintlify-localstorage", onMintlifyStorage);
      clearInterval(pollInterval);
    };
  }, [lang]);
  const resolvedName = useMemo(() => {
    try {
      const value = JSON.parse(lang);
      const useCamelCase = value === "typescript";
      return useCamelCase ? convertToCamelCase(name) : name;
    } catch {
      return name;
    }
  }, [name, lang]);
  return <ResponseField name={resolvedName} {...props}>
			{children}
		</ResponseField>;
};

export const DynamicParamField = ({children, body, path, ...props}) => {
  const convertToCamelCase = str => {
    if (typeof str !== "string") return str;
    return str.replace(/[_-](\w)/g, (_, c) => c.toUpperCase());
  };
  const [lang, setLang] = useState(() => {
    if (typeof window !== "undefined") {
      const stored = localStorage.getItem("code");
      return stored || '"typescript"';
    }
    return '"typescript"';
  });
  useEffect(() => {
    const onMintlifyStorage = event => {
      const key = event.detail?.key;
      if (key === "code") {
        setLang(event.detail.value);
      }
    };
    const pollInterval = setInterval(() => {
      const current = localStorage.getItem("code");
      if (current && current !== lang) {
        setLang(current);
      }
    }, 500);
    document.addEventListener("mintlify-localstorage", onMintlifyStorage);
    return () => {
      document.removeEventListener("mintlify-localstorage", onMintlifyStorage);
      clearInterval(pollInterval);
    };
  }, [lang]);
  const resolvedBody = useMemo(() => {
    try {
      const value = JSON.parse(lang);
      const useCamelCase = value === "typescript";
      return useCamelCase ? convertToCamelCase(body) : body;
    } catch {
      return body;
    }
  }, [body, lang]);
  const resolvedPath = useMemo(() => {
    try {
      const value = JSON.parse(lang);
      const useCamelCase = value === "typescript";
      return useCamelCase ? convertToCamelCase(path) : path;
    } catch {
      return path;
    }
  }, [path, lang]);
  return <ParamField body={resolvedBody} path={resolvedPath} {...props}>
			{children}
		</ParamField>;
};

<Note>
  Track AI token usage against a customer's AI credit system balance. Converts token counts to a dollar cost using [Models.dev](https://models.dev) pricing and your configured markup, then deducts from the customer's credit balance.
</Note>

The `model_id` must use `provider/model` format, matching the provider and model keys from [Models.dev](https://models.dev). For providers with nested model paths (like OpenRouter), include the full path: `openrouter/anthropic/claude-opus-4.6`. The first path segment is the provider key used for provider-level markup lookup.

### Common Use Cases

<CodeGroup>
  ```typescript Anthropic theme={null}
  await autumn.balances.trackTokens({
    customerId: "cus_123",
    modelId: "anthropic/claude-opus-4-6",
    inputTokens: 1000,
    outputTokens: 500
  });
  ```

  ```typescript With cache + reasoning theme={null}
  await autumn.balances.trackTokens({
    customerId: "cus_123",
    modelId: "anthropic/claude-opus-4-6",
    inputTokens: 800,        // excludes the cached tokens below
    outputTokens: 350,       // excludes the reasoning tokens below
    cacheReadTokens: 1000,
    cacheWriteTokens: 200,
    reasoningTokens: 150
  });
  ```

  ```typescript OpenRouter (nested path) theme={null}
  await autumn.balances.trackTokens({
    customerId: "cus_123",
    modelId: "openrouter/anthropic/claude-opus-4.6",
    inputTokens: 2000,
    outputTokens: 1000
  });
  ```

  ```typescript With explicit feature theme={null}
  await autumn.balances.trackTokens({
    customerId: "cus_123",
    featureId: "ai_credits",
    modelId: "anthropic/claude-haiku-4-5",
    inputTokens: 2000,
    outputTokens: 1000
  });
  ```
</CodeGroup>

### Token Pools

Each token parameter is an exclusive pool — no token should be counted in more than one. Each pool is billed at the model's published rate for that pool, falling back to the text input/output rate when the model has none.

<Warning>
  If you pass a provider's raw totals (e.g. OpenAI's `prompt_tokens` and `completion_tokens`), subtract the cache and reasoning counts first — otherwise those tokens are billed twice. The `@useautumn/gateway` wrappers ([AI SDK](/documentation/external-providers/ai-sdk), [OpenRouter](/documentation/external-providers/openrouter)) do this normalization for you.
</Warning>

### Markup Resolution

Markups are optional — the credit system's default markup applies unless overridden per provider or per model. With no markups set, the Models.dev base cost is charged as-is. A markup of `-100` makes the model free — the usage event is still recorded, but nothing is deducted. See [AI Credit Systems](/documentation/modelling-pricing/credit-systems#ai-credit-systems) for configuration.

<Tip>
  `feature_id` is auto-detected when the customer has exactly one AI credit system. The request fails if the customer has none, or has more than one and `feature_id` is omitted.
</Tip>

### Body Parameters

<DynamicParamField body="customer_id" type="string" required>
  The ID of the customer.
</DynamicParamField>

<DynamicParamField body="model_id" type="string" required>
  The AI model in `provider/model` format, matching keys from [Models.dev](https://models.dev) (e.g., `anthropic/claude-opus-4-6`, `openai/gpt-4o`, `openrouter/anthropic/claude-opus-4.6`).
</DynamicParamField>

<DynamicParamField body="input_tokens" type="number" required>
  Number of non-cached text input tokens consumed. Exclusive of the cache and audio token pools.
</DynamicParamField>

<DynamicParamField body="output_tokens" type="number" required>
  Number of text output tokens consumed. Exclusive of the reasoning and audio output pools.
</DynamicParamField>

<DynamicParamField body="cache_read_tokens" type="number">
  Number of cached input tokens read, billed at the model's cache read rate.
</DynamicParamField>

<DynamicParamField body="cache_write_tokens" type="number">
  Number of input tokens written to the cache, billed at the model's cache write rate.
</DynamicParamField>

<DynamicParamField body="reasoning_tokens" type="number">
  Number of reasoning tokens generated, billed at the model's reasoning rate (falls back to the output rate).
</DynamicParamField>

<DynamicParamField body="audio_input_tokens" type="number">
  Number of audio input tokens consumed, billed at the model's audio input rate (falls back to the input rate).
</DynamicParamField>

<DynamicParamField body="audio_output_tokens" type="number">
  Number of audio output tokens generated, billed at the model's audio output rate (falls back to the output rate).
</DynamicParamField>

<DynamicParamField body="feature_id" type="string">
  The ID of the AI credit system feature. If omitted, automatically detects the customer's AI credit system feature. Required when the customer has more than one.
</DynamicParamField>

<DynamicParamField body="entity_id" type="string">
  The ID of the entity for entity-scoped balances.
</DynamicParamField>

<DynamicParamField body="properties" type="object">
  Additional properties to attach to this usage event. The token counts and a pricing breakdown (`cost`, `base_cost`, `markup`, `markup_source`, `tier_applied`, `rates`) are automatically included.
</DynamicParamField>

### Response

<DynamicResponseField name="customer_id" type="string">
  The ID of the customer whose token usage was tracked.
</DynamicResponseField>

<DynamicResponseField name="value" type="number">
  The dollar cost that was deducted from the customer's AI credit balance.
</DynamicResponseField>

<DynamicResponseField name="balance" type="object | null">
  The updated balance for the AI credit system feature.

  <Expandable title="properties">
    <DynamicResponseField name="feature_id" type="string">
      The feature ID this balance is for.
    </DynamicResponseField>

    <DynamicResponseField name="granted" type="number">
      Total balance granted (included + prepaid).
    </DynamicResponseField>

    <DynamicResponseField name="remaining" type="number">
      Remaining balance available for use.
    </DynamicResponseField>

    <DynamicResponseField name="usage" type="number">
      Total usage consumed in the current period.
    </DynamicResponseField>

    <DynamicResponseField name="unlimited" type="boolean">
      Whether this feature has unlimited usage.
    </DynamicResponseField>

    <DynamicResponseField name="overage_allowed" type="boolean">
      Whether usage beyond the granted balance is allowed.
    </DynamicResponseField>

    <DynamicResponseField name="next_reset_at" type="number | null">
      Timestamp when the balance will reset, or null for no reset.
    </DynamicResponseField>
  </Expandable>
</DynamicResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "customer_id": "cus_123",
    "value": 0.06,
    "balance": {
      "feature_id": "ai_credits",
      "granted": 10.00,
      "remaining": 9.94,
      "usage": 0.06,
      "unlimited": false,
      "overage_allowed": false,
      "next_reset_at": 1773851121437,
      "breakdown": [
        {
          "id": "cus_ent_abc123",
          "plan_id": "pro_plan",
          "included_grant": 10.00,
          "prepaid_grant": 0,
          "remaining": 9.94,
          "usage": 0.06,
          "unlimited": false,
          "reset": {
            "interval": "month",
            "resets_at": 1773851121437
          },
          "price": null,
          "expires_at": null
        }
      ]
    }
  }
  ```
</ResponseExample>


## OpenAPI

````yaml openapi POST /v1/balances.track_tokens
openapi: 3.1.0
info:
  title: Autumn API
  version: 2.3.0
servers:
  - url: https://api.useautumn.com
    description: Production server
security:
  - secretKey: []
paths:
  /v1/balances.track_tokens:
    post:
      description: >-
        Records AI token usage for a customer and returns the updated AI credit
        balance.


        Use this after an LLM request when you have input and output token
        counts. Autumn converts token usage to a dollar amount using the
        configured model pricing and markup, then tracks that value against the
        customer's AI credit system.
      operationId: trackTokens
      parameters:
        - name: x-api-version
          in: header
          required: true
          schema:
            type: string
            default: 2.3.0
          x-speakeasy-globals-hidden: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                customer_id:
                  type: string
                  description: The ID of the customer.
                entity_id:
                  type: string
                  description: The ID of the entity for entity-scoped balances.
                feature_id:
                  type: string
                  description: >-
                    The ID of the AI credit system feature. Auto-detected from
                    the customer's entitlements if omitted — only required when
                    a customer has multiple AI credit systems.
                model_id:
                  type: string
                  description: >-
                    The AI model as '[provider]/[model]' (e.g.
                    'anthropic/claude-opus-4-8', 'openrouter/openai/gpt-4o').
                    The provider is the first path segment and must match a
                    provider + model key in models.dev.
                input_tokens:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  description: >-
                    Number of non-cached text input tokens consumed. Exclusive
                    of cache and audio token pools.
                output_tokens:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  description: >-
                    Number of text output tokens consumed. Exclusive of the
                    reasoning and audio output pools.
                cache_read_tokens:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  description: Number of cached input tokens read.
                cache_write_tokens:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  description: Number of input tokens written to the cache.
                audio_input_tokens:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  description: Number of audio input tokens consumed.
                audio_output_tokens:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  description: Number of audio output tokens generated.
                reasoning_tokens:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  description: Number of reasoning tokens generated.
                properties:
                  type: object
                  propertyNames:
                    type: string
                  additionalProperties: {}
                  description: Additional properties to attach to this usage event.
                timestamp:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                  exclusiveMinimum: 0
                  description: >-
                    Unix timestamp in milliseconds to use for the usage event.
                    Defaults to the current time.
                overage_behavior:
                  description: >-
                    How to handle usage that exceeds the available balance.
                    "cap" (default) deducts only what fits, stopping at zero.
                    "overflow" deducts the full value: the balance can go
                    negative and usage limits do not clamp the deduction, though
                    spend limits still apply.
                  enum:
                    - cap
                    - overflow
                  type: string
                async:
                  type: boolean
                  description: >-
                    If true, enqueue the event for asynchronous processing and
                    return 204 immediately. The response will not include
                    balance information.
              required:
                - customer_id
                - model_id
                - input_tokens
                - output_tokens
              title: TrackTokensParams
              examples:
                - customer_id: cus_123
                  feature_id: ai_credits
                  model_id: anthropic/claude-sonnet-4-20250514
                  input_tokens: 1000
                  output_tokens: 500
            example:
              customer_id: cus_123
              feature_id: ai_credits
              model_id: anthropic/claude-sonnet-4-20250514
              input_tokens: 1000
              output_tokens: 500
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  customer_id:
                    type: string
                    description: The ID of the customer whose usage was tracked.
                  entity_id:
                    type: string
                    description: >-
                      The ID of the entity, if entity-scoped tracking was
                      performed.
                  event_name:
                    type: string
                    description: >-
                      The event name that was tracked, if event_name was used
                      instead of feature_id.
                  value:
                    type: number
                    description: The amount of usage that was recorded.
                  balance:
                    anyOf:
                      - $ref: '#/components/schemas/Balance'
                      - type: 'null'
                    description: >-
                      The updated balance for the tracked feature. Null if
                      tracking by event_name that affects multiple features.
                  balances:
                    type: object
                    propertyNames:
                      type: string
                    additionalProperties:
                      anyOf:
                        - $ref: '#/components/schemas/Balance'
                        - type: 'null'
                    description: >-
                      Map of feature_id to updated balance for the tracked
                      feature and any related features (e.g. linked credit
                      systems). Value is null when the customer has no balance
                      for that feature.
                  deductions:
                    type: array
                    items:
                      type: object
                      properties:
                        balance_id:
                          type: string
                          description: >-
                            ID of the underlying balance row that was deducted
                            from (customer_entitlement or rollover).
                        feature_id:
                          type: string
                          description: The feature this balance belongs to.
                        plan_id:
                          anyOf:
                            - type: string
                            - type: 'null'
                          description: >-
                            ID of the plan/product this balance belongs to. Null
                            when the balance can't be attributed to a single
                            plan (e.g. it spans multiple).
                        reset:
                          anyOf:
                            - type: object
                              properties:
                                interval:
                                  anyOf:
                                    - enum:
                                        - one_off
                                        - minute
                                        - hour
                                        - day
                                        - week
                                        - month
                                        - quarter
                                        - semi_annual
                                        - year
                                      type: string
                                    - const: multiple
                                  description: >-
                                    The reset interval (hour, day, week, month,
                                    etc.) or 'multiple' if combined from
                                    different intervals.
                                interval_count:
                                  type: number
                                  description: >-
                                    Number of intervals between resets (eg. 2
                                    for bi-monthly).
                                resets_at:
                                  anyOf:
                                    - type: number
                                    - type: 'null'
                                  description: Timestamp when the balance will next reset.
                              required:
                                - interval
                                - resets_at
                            - type: 'null'
                          description: >-
                            Reset configuration for the balance this deduction
                            came from, or null if the balance doesn't reset.
                        value:
                          type: number
                          description: >-
                            Amount deducted from this balance. Positive when
                            usage was consumed, negative when credit was
                            restored (e.g. a refund via negative track value).
                      required:
                        - balance_id
                        - feature_id
                        - plan_id
                        - reset
                        - value
                    description: >-
                      Per-balance breakdown of what this event deducted. A
                      single event can consume from multiple balance rows when
                      credit systems or rollovers are involved; this surfaces
                      each one so callers can build per-feature usage views
                      without polling.
                required:
                  - customer_id
                  - value
                  - balance
                examples:
                  - customer_id: cus_123
                    value: 0.006
                    balance:
                      feature_id: ai_credits
                      granted: 10
                      remaining: 9.994
                      usage: 0.006
                      unlimited: false
                      overage_allowed: false
                      max_purchase: null
                      next_reset_at: 1773851121437
                      breakdown:
                        - id: cus_ent_39qmLooixXLAqMywgXywjAz96rV
                          plan_id: pro_plan
                          included_grant: 100
                          prepaid_grant: 0
                          remaining: 72
                          usage: 28
                          unlimited: false
                          reset:
                            interval: month
                            resets_at: 1773851121437
                          price: null
                          expires_at: null
                    deductions:
                      - balance_id: cus_ent_3DdSDoyFmoA9Neecl2a2Gc507X2
                        feature_id: ai_credits
                        plan_id: pro
                        reset:
                          interval: month
                          resets_at: 1781288736881
                        value: 0.006
              example:
                customer_id: cus_123
                value: 0.006
                balance:
                  feature_id: ai_credits
                  granted: 10
                  remaining: 9.994
                  usage: 0.006
                  unlimited: false
                  overage_allowed: false
                  max_purchase: null
                  next_reset_at: 1773851121437
                  breakdown:
                    - id: cus_ent_39qmLooixXLAqMywgXywjAz96rV
                      plan_id: pro_plan
                      included_grant: 100
                      prepaid_grant: 0
                      remaining: 72
                      usage: 28
                      unlimited: false
                      reset:
                        interval: month
                        resets_at: 1773851121437
                      price: null
                      expires_at: null
                deductions:
                  - balance_id: cus_ent_3DdSDoyFmoA9Neecl2a2Gc507X2
                    feature_id: ai_credits
                    plan_id: pro
                    reset:
                      interval: month
                      resets_at: 1781288736881
                    value: 0.006
        '202':
          description: >-
            Accepted. Autumn is experiencing degraded service from a downstream
            provider, so the token usage event was accepted for replay and will
            be tracked as soon as the service is restored.
          content:
            application/json:
              schema:
                type: object
                properties:
                  customer_id:
                    type: string
                    description: The ID of the customer whose usage was tracked.
                  entity_id:
                    type: string
                    description: >-
                      The ID of the entity, if entity-scoped tracking was
                      performed.
                  event_name:
                    type: string
                    description: >-
                      The event name that was tracked, if event_name was used
                      instead of feature_id.
                  value:
                    type: number
                    description: The amount of usage that was recorded.
                  balance:
                    anyOf:
                      - $ref: '#/components/schemas/Balance'
                      - type: 'null'
                    description: >-
                      The updated balance for the tracked feature. Null if
                      tracking by event_name that affects multiple features.
                  balances:
                    type: object
                    propertyNames:
                      type: string
                    additionalProperties:
                      anyOf:
                        - $ref: '#/components/schemas/Balance'
                        - type: 'null'
                    description: >-
                      Map of feature_id to updated balance for the tracked
                      feature and any related features (e.g. linked credit
                      systems). Value is null when the customer has no balance
                      for that feature.
                  deductions:
                    type: array
                    items:
                      type: object
                      properties:
                        balance_id:
                          type: string
                          description: >-
                            ID of the underlying balance row that was deducted
                            from (customer_entitlement or rollover).
                        feature_id:
                          type: string
                          description: The feature this balance belongs to.
                        plan_id:
                          anyOf:
                            - type: string
                            - type: 'null'
                          description: >-
                            ID of the plan/product this balance belongs to. Null
                            when the balance can't be attributed to a single
                            plan (e.g. it spans multiple).
                        reset:
                          anyOf:
                            - type: object
                              properties:
                                interval:
                                  anyOf:
                                    - enum:
                                        - one_off
                                        - minute
                                        - hour
                                        - day
                                        - week
                                        - month
                                        - quarter
                                        - semi_annual
                                        - year
                                      type: string
                                    - const: multiple
                                  description: >-
                                    The reset interval (hour, day, week, month,
                                    etc.) or 'multiple' if combined from
                                    different intervals.
                                interval_count:
                                  type: number
                                  description: >-
                                    Number of intervals between resets (eg. 2
                                    for bi-monthly).
                                resets_at:
                                  anyOf:
                                    - type: number
                                    - type: 'null'
                                  description: Timestamp when the balance will next reset.
                              required:
                                - interval
                                - resets_at
                            - type: 'null'
                          description: >-
                            Reset configuration for the balance this deduction
                            came from, or null if the balance doesn't reset.
                        value:
                          type: number
                          description: >-
                            Amount deducted from this balance. Positive when
                            usage was consumed, negative when credit was
                            restored (e.g. a refund via negative track value).
                      required:
                        - balance_id
                        - feature_id
                        - plan_id
                        - reset
                        - value
                    description: >-
                      Per-balance breakdown of what this event deducted. A
                      single event can consume from multiple balance rows when
                      credit systems or rollovers are involved; this surfaces
                      each one so callers can build per-feature usage views
                      without polling.
                required:
                  - customer_id
                  - value
                  - balance
                examples:
                  - customer_id: cus_123
                    value: 0.006
                    balance:
                      feature_id: ai_credits
                      granted: 10
                      remaining: 9.994
                      usage: 0.006
                      unlimited: false
                      overage_allowed: false
                      max_purchase: null
                      next_reset_at: 1773851121437
                      breakdown:
                        - id: cus_ent_39qmLooixXLAqMywgXywjAz96rV
                          plan_id: pro_plan
                          included_grant: 100
                          prepaid_grant: 0
                          remaining: 72
                          usage: 28
                          unlimited: false
                          reset:
                            interval: month
                            resets_at: 1773851121437
                          price: null
                          expires_at: null
                    deductions:
                      - balance_id: cus_ent_3DdSDoyFmoA9Neecl2a2Gc507X2
                        feature_id: ai_credits
                        plan_id: pro
                        reset:
                          interval: month
                          resets_at: 1781288736881
                        value: 0.006
              example:
                customer_id: cus_123
                value: 0.006
                balance:
                  feature_id: ai_credits
                  granted: 10
                  remaining: 9.994
                  usage: 0.006
                  unlimited: false
                  overage_allowed: false
                  max_purchase: null
                  next_reset_at: 1773851121437
                  breakdown:
                    - id: cus_ent_39qmLooixXLAqMywgXywjAz96rV
                      plan_id: pro_plan
                      included_grant: 100
                      prepaid_grant: 0
                      remaining: 72
                      usage: 28
                      unlimited: false
                      reset:
                        interval: month
                        resets_at: 1773851121437
                      price: null
                      expires_at: null
                deductions:
                  - balance_id: cus_ent_3DdSDoyFmoA9Neecl2a2Gc507X2
                    feature_id: ai_credits
                    plan_id: pro
                    reset:
                      interval: month
                      resets_at: 1781288736881
                    value: 0.006
      x-codeSamples:
        - lang: typescript
          label: Typescript (SDK)
          source: |-
            import { Autumn } from 'autumn-js'

            const autumn = new Autumn()

            const result = await autumn.trackTokens({
              customerId: "cus_123",
              featureId: "ai_credits",
              modelId: "anthropic/claude-sonnet-4-20250514",
              inputTokens: 1000,
              outputTokens: 500,
            });
        - lang: python
          label: Python (SDK)
          source: |-
            from autumn_sdk import Autumn

            autumn = Autumn(secret_key="am_sk_test...")

            res = autumn.track_tokens(
                customer_id="cus_123",
                model_id="anthropic/claude-sonnet-4-20250514",
                input_tokens=1000,
                output_tokens=500,
                feature_id="ai_credits",
            )
components:
  schemas:
    Balance:
      type: object
      properties:
        feature_id:
          type: string
          description: The feature ID this balance is for.
        feature:
          type: object
          properties:
            id:
              type: string
              description: >-
                The unique identifier for this feature, used in /check and
                /track calls.
            name:
              type: string
              description: Human-readable name displayed in the dashboard and billing UI.
            type:
              enum:
                - boolean
                - metered
                - credit_system
                - ai_credit_system
              type: string
              description: >-
                Feature type: 'boolean' for on/off access, 'metered' for
                usage-tracked features, 'credit_system' for unified credit
                pools, 'ai_credit_system' for model-based token pricing.
            consumable:
              type: boolean
              description: >-
                For metered features: true if usage resets periodically (API
                calls, credits), false if allocated persistently (seats,
                storage).
            event_names:
              type: array
              items:
                type: string
              description: >-
                Event names that trigger this feature's balance. Allows multiple
                features to respond to a single event.
            credit_schema:
              type: array
              items:
                type: object
                properties:
                  metered_feature_id:
                    type: string
                    description: >-
                      ID of the metered feature that draws from this credit
                      system.
                  credit_cost:
                    type: number
                    description: Credits consumed per unit of the metered feature.
                required:
                  - metered_feature_id
                  - credit_cost
              description: >-
                For credit_system features: maps metered features to their
                credit costs.
            model_markups:
              anyOf:
                - type: object
                  propertyNames:
                    type: string
                  additionalProperties:
                    type: object
                    properties:
                      markup:
                        type: number
                        minimum: -100
                      input_cost:
                        type: number
                        minimum: 0
                      output_cost:
                        type: number
                        minimum: 0
                - type: 'null'
              description: Per-model markup overrides for AI credit systems.
            default_markup:
              type: number
              minimum: -100
              description: >-
                Default percentage markup for AI credit systems. Use -100 to
                make usage free.
            provider_markups:
              anyOf:
                - type: object
                  propertyNames:
                    type: string
                  additionalProperties:
                    type: object
                    properties:
                      markup:
                        type: number
                        minimum: -100
                    required:
                      - markup
                - type: 'null'
              description: Per-provider default markup percentages for AI credit systems.
            display:
              type: object
              properties:
                singular:
                  anyOf:
                    - type: string
                    - type: 'null'
                  description: Singular form for UI display (e.g., 'API call', 'seat').
                plural:
                  anyOf:
                    - type: string
                    - type: 'null'
                  description: Plural form for UI display (e.g., 'API calls', 'seats').
              description: >-
                Display names for the feature in billing UI and customer-facing
                components.
            archived:
              type: boolean
              description: Whether the feature is archived and hidden from the dashboard.
          required:
            - id
            - name
            - type
            - consumable
            - archived
          description: The full feature object if expanded.
        granted:
          type: number
          description: Total balance granted (included + prepaid).
        remaining:
          type: number
          minimum: 0
          description: Remaining balance available for use.
        usage:
          type: number
          description: Total usage consumed in the current period.
        unlimited:
          type: boolean
          description: Whether this feature has unlimited usage.
        overage_allowed:
          type: boolean
          description: >-
            Whether usage beyond the granted balance is allowed (with overage
            charges).
        max_purchase:
          anyOf:
            - type: number
            - type: 'null'
          description: >-
            Maximum quantity that can be purchased as a top-up, or null for
            unlimited.
        next_reset_at:
          anyOf:
            - type: number
            - type: 'null'
          description: Timestamp when the balance will reset, or null for no reset.
        breakdown:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                default: ''
                description: The unique identifier for this balance breakdown.
              plan_id:
                anyOf:
                  - type: string
                  - type: 'null'
                description: >-
                  The plan ID this balance originates from, or null for
                  standalone balances.
              included_grant:
                type: number
                description: Amount granted from the plan's included usage.
              prepaid_grant:
                type: number
                description: Amount granted from prepaid purchases or top-ups.
              remaining:
                type: number
                description: Remaining balance available for use.
              usage:
                type: number
                description: Amount consumed in the current period.
              unlimited:
                type: boolean
                description: Whether this balance has unlimited usage.
              reset:
                anyOf:
                  - type: object
                    properties:
                      interval:
                        anyOf:
                          - enum:
                              - one_off
                              - minute
                              - hour
                              - day
                              - week
                              - month
                              - quarter
                              - semi_annual
                              - year
                            type: string
                          - const: multiple
                        description: >-
                          The reset interval (hour, day, week, month, etc.) or
                          'multiple' if combined from different intervals.
                      interval_count:
                        type: number
                        description: >-
                          Number of intervals between resets (eg. 2 for
                          bi-monthly).
                      resets_at:
                        anyOf:
                          - type: number
                          - type: 'null'
                        description: Timestamp when the balance will next reset.
                    required:
                      - interval
                      - resets_at
                  - type: 'null'
                description: Reset configuration for this balance, or null if no reset.
              price:
                anyOf:
                  - type: object
                    properties:
                      amount:
                        type: number
                        description: The per-unit price amount.
                      tiers:
                        type: array
                        items:
                          type: object
                          properties:
                            to:
                              anyOf:
                                - type: number
                                - const: inf
                            amount:
                              type: number
                            flat_amount:
                              type: number
                          required:
                            - to
                            - amount
                        description: Tiered pricing configuration if applicable.
                      tier_behavior:
                        enum:
                          - graduated
                          - volume
                        type: string
                        description: >-
                          How tiers are applied: graduated (split across bands)
                          or volume (flat rate for the matched tier).
                      billing_units:
                        type: number
                        description: >-
                          The number of units per billing increment (eg. $9 /
                          250 units).
                      billing_method:
                        enum:
                          - prepaid
                          - usage_based
                        type: string
                        description: Whether usage is prepaid or billed pay-per-use.
                      max_purchase:
                        anyOf:
                          - type: number
                          - type: 'null'
                        description: >-
                          Maximum quantity that can be purchased, or null for
                          unlimited.
                    required:
                      - billing_units
                      - billing_method
                      - max_purchase
                  - type: 'null'
                description: Pricing configuration if this balance has usage-based pricing.
              expires_at:
                anyOf:
                  - type: number
                  - type: 'null'
                description: >-
                  Timestamp when this balance expires, or null for no
                  expiration.
            required:
              - plan_id
              - included_grant
              - prepaid_grant
              - remaining
              - usage
              - unlimited
              - reset
              - price
              - expires_at
          description: >-
            Detailed breakdown of balance sources when stacking multiple plans
            or grants.
        rollovers:
          type: array
          items:
            type: object
            properties:
              balance:
                type: number
                description: Amount of balance rolled over from a previous period.
              expires_at:
                type: number
                description: Timestamp when the rollover balance expires.
            required:
              - balance
              - expires_at
          description: Rollover balances carried over from previous periods.
      required:
        - feature_id
        - granted
        - remaining
        - usage
        - unlimited
        - overage_allowed
        - max_purchase
        - next_reset_at
      examples:
        - feature_id: messages
          granted: 100
          remaining: 72
          usage: 28
          unlimited: false
          overage_allowed: false
          max_purchase: null
          next_reset_at: 1773851121437
          breakdown:
            - id: cus_ent_39qmLooixXLAqMywgXywjAz96rV
              plan_id: pro_plan
              included_grant: 100
              prepaid_grant: 0
              remaining: 72
              usage: 28
              unlimited: false
              reset:
                interval: month
                resets_at: 1773851121437
              price: null
              expires_at: null
  securitySchemes:
    secretKey:
      type: http
      scheme: bearer
      bearerFormat: JWT

````