Skip to main content
Credit systems let you track actions with different credit costs from a single balance pool. A credit system is made up of a list of features that can draw from it, and a credit cost per unit of usage for each feature.
Example
You have a Pro plan that gives users 100 basic messages per month, and 10 premium messages per month. These 2 balances are separate and independent of each other. To give your users more flexibility, you instead decide to use a credit system, where:
  • basic message: costs 1 credit per message
  • premium message: costs 10 credits per message
Instead of having 2 separate balances for each message type, your Pro plan can have 200 credits per month. Your users can use the credits in any combination of basic and premium messages they want.

Creating a credit system

Make sure you have some metered features created before creating a credit system.
Define metered features, then create a credit_system feature with a creditSchema that maps each feature to a credit cost:
autumn.config.ts
import { feature, item, plan } from 'atmn';

export const basicMessage = feature({
  id: 'basic_message',
  name: 'Basic Message',
  type: 'metered',
  consumable: true,
});

export const premiumMessage = feature({
  id: 'premium_message',
  name: 'Premium Message',
  type: 'metered',
  consumable: true,
});

export const credits = feature({
  id: 'credits',
  name: 'Credits',
  type: 'credit_system',
  creditSchema: [
    { meteredFeatureId: basicMessage.id, creditCost: 1 },
    { meteredFeatureId: premiumMessage.id, creditCost: 10 },
  ],
});

export const pro = plan({
  id: 'pro',
  name: 'Pro',
  price: { amount: 20, interval: 'month' },
  items: [
    item({
      featureId: credits.id,
      included: 200,
      reset: { interval: 'month' },
    }),
  ],
});
Push changes with atmn push.
ExampleIf each premium_request is worth 3 credits, then using 6 premium requests will cost 18 credits.
Now you can add this credit system to a plan, such as granting 50 credits per month or charging $1 per credit.

Tracking and limiting credit usage

When implementing a credit system into your application, you should interact with the underlying features — not the credit system itself. This means passing in the underlying feature_id when checking or tracking usage.

Checking access

Before allowing a customer to use a feature, check if they have enough credits to do so. If each “premium request” is worth 3 credits, then this example will check if the customer has at least 18 credits remaining.
import { Autumn } from "autumn-js";

const autumn = new Autumn({ secretKey: "am_sk_test_1234" });

const response = await autumn.customers.check({
  customerId: "user_123",
  featureId: "premium_request",
  requiredBalance: 6,
});

console.log(response.allowed);
In this case, we have a balance of 100 credits remaining, so we’re allowed to use our 6 “premium requests” feature.
If a feature is not defined in the credit system, it will return allowed: false

Tracking usage

Since the customer has sufficient credits, you can let them use their 6 “premium requests”. Afterwards, you can track the usage to update their balance. This will decrement the customer’s balance by 18 credits (6 requests * 3 credits per request).
import { Autumn } from "autumn-js";

const autumn = new Autumn({ secretKey: "am_sk_test_1234" });

await autumn.customers.track({
  customerId: "user_123",
  featureId: "premium_request",
  value: 6,
});
Since the customer started with a balance of 100 credits, and used 18 credits, their remaining balance is 82 credits.

Stacking with direct balances

A feature can have both a direct balance and belong to a credit system. When this happens, the balances stack and direct balances are always consumed before credit system balances, regardless of interval.
Example
A customer’s plan grants 10 premium messages per month directly, plus 200 credits per month from a credit system (where each premium message costs 10 credits).

When the customer sends a premium message, Autumn deducts from the direct premium message balance first. Once those 10 direct messages are used up, subsequent premium messages draw from the credit pool instead.
The check endpoint accounts for both balances. If the customer has 5 direct premium messages remaining plus 100 credits (enough for 10 more premium messages), check will report that the customer is allowed.

Monetary credits

You may want your credit system to represent a monetary value: eg, $10 of credits. To implement this, you can map each credit to a cent value (eg, 1 credit = 1 cent).
  1. When creating your credit system, define credit amounts in the per-cent cost
Eg: if each premium_request costs 3 cents, our credit cost should be 3.
  1. When adding the credits to a plan, set the granted amount of credits in cents
Eg, if customers get 5 USD credits for free, they should have an included usage of 500.
  1. When charging for the credits, set the cost of each credit to 1 cent
See the credits pricing guide for a more detailed example of setting up a monetary credits system

Credits Example

AI Credit Systems

For AI applications that need to track token usage with per-model pricing, you can create an AI credit system. This lets you define markup percentages for each model and automatically calculate costs based on input/output tokens.
Markups are optional. defaultMarkup applies to every model unless overridden — by providerMarkups (keyed by the first segment of the model ID, e.g. openrouter), or by modelMarkups for a specific model, which takes highest priority. With no markups set, models are billed at their Models.dev base cost.A markup of -100 makes the model free: usage events are still recorded, but nothing is deducted from the balance.
Simplest setup — one markup for everything
export const aiCredits = feature({
  id: 'ai_credits',
  name: 'AI Credits',
  type: 'ai_credit_system',
  defaultMarkup: 30, // every model billed at models.dev cost + 30%
});
Or mix the levels for finer control:
autumn.config.ts
import { feature, item, plan } from 'atmn';

export const aiCredits = feature({
  id: 'ai_credits',
  name: 'AI Credits',
  type: 'ai_credit_system',
  // Global fallback markup
  defaultMarkup: 30,
  // Per-provider defaults
  providerMarkups: {
    openrouter: { markup: 25 },
  },
  // Per-model overrides (highest priority)
  modelMarkups: {
    'anthropic/claude-opus-4-5': { markup: 20 },
    'anthropic/claude-sonnet-4-5': { markup: 15 },
    'openai/gpt-4o-mini': { markup: -100 }, // free for customers
    // For custom/self-hosted models, specify input/output costs in $/M tokens
    'custom/my-model': { markup: 25, inputCost: 0.01, outputCost: 0.03 },
  },
});

export const pro = plan({
  id: 'pro',
  name: 'Pro',
  price: { amount: 50, interval: 'month' },
  items: [
    item({
      featureId: aiCredits.id,
      included: 10, // $10 worth of AI credits
      reset: { interval: 'month' },
    }),
  ],
});
Push changes with atmn push.

Model ID Format

Model IDs follow the provider/model format:
  • Standard models: anthropic/claude-opus-4-5, openai/gpt-4o
  • OpenRouter models: openrouter/anthropic/claude-opus-4.6
  • Custom models: custom/my-model-name
For standard models, pricing is automatically fetched from models.dev, including separate rates for cache reads/writes, reasoning, and audio tokens where the model publishes them, plus large-context tier pricing (e.g. above 200k input tokens) when applicable. For custom models, you must specify both inputCost and outputCost in dollars per million tokens — tracking fails if either is missing. Custom models bill input and output tokens only; cache, reasoning, and audio pools are ignored.

Tracking Token Usage

Use the trackTokens endpoint to deduct credits based on token usage:
import { Autumn } from "autumn-js";

const autumn = new Autumn({ secretKey: "am_sk_test_1234" });

await autumn.balances.trackTokens({
  customerId: "user_123",
  modelId: "anthropic/claude-opus-4-5",
  inputTokens: 1500,
  outputTokens: 500,
});
The cost is calculated automatically based on the model’s pricing plus your configured markup percentage.