Pricing DSL
Type-safe pricing expressions with mul, add, tag, inputTokens, and more
Scrawn includes a type-safe domain-specific language for expressing pricing logic. Use it inline wherever a debit or Debit value is accepted.
Functions
tag(name) Events & AI
Reference a price tag managed on the backend.
import { tag } from "@scrawn/core";
tag("PREMIUM_CALL"); // Resolved to cent amount by backend
tag("EXTRA_FEE");amount(cents) Events & AI
Explicit cent amount as an expression node (useful inside compound expressions).
import { amount } from "@scrawn/core";
amount(500); // $5.00mul(...args) Events & AI
Multiply two or more values.
import { mul, tag } from "@scrawn/core";
mul(tag("PER_TOKEN"), 100);
mul(tag("BASE_RATE"), 2, tag("MULTIPLIER"));add(...args) Events & AI
Add two or more values.
import { add, tag, amount } from "@scrawn/core";
add(tag("PREMIUM_CALL"), tag("EXTRA_FEE"));
add(tag("BASE"), 250, amount(100));sub(...args) Events & AI
Subtract values.
import { sub, tag } from "@scrawn/core";
sub(tag("GROSS"), tag("DISCOUNT"));div(...args) Events & AI
Integer division.
import { div, tag } from "@scrawn/core";
div(tag("TOTAL"), 2);inputTokens() AI only
outputTokens() AI only
Token count placeholders that resolve to the actual token count of the current AI call. Only valid inside AITokenUsagePayload objects.
import { mul, tag, inputTokens, outputTokens } from "@scrawn/core";
mul(biller.tag("GPT_INPUT_RATE"), inputTokens());
mul(biller.tag("GPT_OUTPUT_RATE"), outputTokens());Usage in Events
Pass a pricing expression where a debit value is accepted:
import { scrawn, mul, tag } from "@scrawn/core";
const biller = scrawn({
apiKey: process.env.SCRAWN_KEY,
baseURL: process.env.SCRAWN_BASE_URL,
});
// Tag reference
await biller.basicUsageEventConsumer({
userId: "user-123",
debit: tag("PREMIUM_CALL"),
});
// Compound expression
await biller.basicUsageEventConsumer({
userId: "user-123",
debit: mul(tag("PER_CALL"), 3),
});For AI token billing, use inputTokens() and outputTokens() as placeholders:
async function* generateUsage() {
yield {
userId: "user-123",
model: "gpt-4",
inputTokens: 100,
outputTokens: 50,
inputDebit: mul(biller.tag("GPT_INPUT_RATE"), inputTokens()),
outputDebit: mul(biller.tag("GPT_OUTPUT_RATE"), outputTokens()),
};
}
await biller.aiTokenStreamConsumer(generateUsage());Persisted Expressions
Store complex expressions on the backend and reference them by name:
// Reference a saved expression
await biller.basicUsageEventConsumer({
userId: "user-123",
debit: biller.expr("MY_PRICING_EXPR"),
});Error Handling
Invalid expressions (wrong types, missing operands, etc.) throw PricingExpressionError at runtime. The TypeScript types catch most issues at compile time.