# How OpenSEO's Billing Credit System and Markup Calculation Works

> Discover how OpenSEO's billing credit system deducts costs from subscription and top-up balances. Learn about its configurable markup for USD invoicing.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: internals
- Published: 2026-06-26

---

**OpenSEO deducts API usage costs from a dual-balance credit pool—spending subscription credits first, then top-up credits—and applies a configurable platform markup when converting consumed credits to USD for invoicing.**

OpenSEO, the open-source SEO platform from `every-app/open-seo`, tracks every paid operation against a shared organizational credit pool. Understanding how this **OpenSEO billing credit system** calculates costs and applies markup is essential for developers integrating with DataForSEO APIs or managing white-label subscriptions.

## Credit Pool Architecture and Deduction Logic

The system maintains two distinct balances at the organization level:

- **usage_credits**: Credits earned from monthly subscription plans. These are always spent first.
- **topup_credits**: One-off credits purchased as emergency top-ups. These act as a secondary reserve, consumed only when **usage_credits** are depleted.

When a paid tool executes—such as a DataForSEO API call or rank-tracking job—the system deducts credits in strict order: first draining **usage_credits**, then falling back to **topup_credits**.

### Feature-Based Credit Costs

Each operation declares its cost profile via a `creditFeature` identifier. For example, keyword research operations specify `"keyword_research"` while rank-tracking jobs use `"rank_tracking"`. The actual credit cost per call is determined by the external API pricing (e.g., 30–100 credits per keyword) and mapped internally.

## Converting Credits to USD

Raw credits convert to monetary values using a fixed ratio defined in [`src/shared/billing.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/billing.ts). The helper function `autumnSeoDataCreditsToUsd` performs this calculation using the constant `AUTUMN_SEO_DATA_CREDITS_PER_USD`:

```typescript
// src/shared/billing.ts
const AUTUMN_SEO_DATA_CREDITS_PER_USD = 1000;

function autumnSeoDataCreditsToUsd(credits: number): number {
  return credits / AUTUMN_SEO_DATA_CREDITS_PER_USD;
}

```

This conversion yields the base cost before platform fees.

## Platform Markup Application

In [`src/server/billing/subscription.ts`](https://github.com/every-app/open-seo/blob/main/src/server/billing/subscription.ts), the subscription billing logic converts consumed credits to USD and applies the **platform markup**. The markup rate is controlled by the `PLATFORM_MARKUP_RATE` constant (e.g., `0.20` for 20%):

```typescript
// src/server/billing/subscription.ts
const PLATFORM_MARKUP_RATE = 0.20;

const rawUsd = autumnSeoDataCreditsToUsd(creditsSpent);
const finalCharge = rawUsd * (1 + PLATFORM_MARKUP_RATE);

```

The markup is calculated dynamically during invoicing. Internal credit pools always store raw credit values, ensuring the markup affects only the final charge amount, not the balance tracking.

## Source Files and Implementation

The billing mechanism spans several TypeScript modules:

| File | Purpose |
|------|---------|
| [`src/shared/billing.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/billing.ts) | Defines credit constants (`AUTUMN_SEO_DATA_TOP_UP_PLAN_ID`, `AUTUMN_SEO_DATA_CREDITS_PER_USD`) and the `autumnSeoDataCreditsToUsd` conversion helper. |
| [`src/server/billing/subscription.ts`](https://github.com/every-app/open-seo/blob/main/src/server/billing/subscription.ts) | Implements subscription logic, credit-to-USD conversion, and markup application during invoicing. |
| [`src/server/mcp/tools/whoami.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/whoami.ts) | Exposes the current credit balance via the `creditsRemaining` field in the MCP "whoami" tool response. |
| [`src/server/features/keywords/services/research/research.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/keywords/services/research/research.ts) | Demonstrates `creditFeature: "keyword_research"` assignment for credit costing. |
| [`src/server/features/rank-tracking/services/RankTrackingService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/rank-tracking/services/RankTrackingService.ts) | Shows `creditFeature: "rank_tracking"` usage and credit deduction patterns. |

## Summary

- OpenSEO uses a dual-balance system with **usage_credits** (subscription) and **topup_credits** (one-off purchases).
- Credits deduct in priority order: subscription credits first, top-ups second.
- The `autumnSeoDataCreditsToUsd` function converts credits to dollars using a fixed ratio defined in [`src/shared/billing.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/billing.ts).
- **PLATFORM_MARKUP_RATE** inflates the raw USD amount only during invoicing, leaving internal credit balances unaffected.
- Each feature declares its cost profile via `creditFeature` identifiers in their respective service files.

## Frequently Asked Questions

### What happens when both usage_credits and topup_credits run out?

When an organization's **usage_credits** and **topup_credits** are both depleted, subsequent API calls will fail with an insufficient credits error. Users must purchase a top-up or upgrade their subscription plan to resume paid operations.

### Where is the current credit balance stored and exposed?

The organization-level credit balances are stored in the database and exposed through the `whoami` MCP tool implemented in [`src/server/mcp/tools/whoami.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/whoami.ts). This returns the `creditsRemaining` field showing the combined available balance.

### How is the markup rate configured?

The markup percentage is hardcoded as `PLATFORM_MARKUP_RATE` in [`src/server/billing/subscription.ts`](https://github.com/every-app/open-seo/blob/main/src/server/billing/subscription.ts). Developers can modify this constant to adjust the platform fee applied to all billing calculations before they reach the payment processor.

### Do credit costs vary by DataForSEO endpoint?

Yes. While the internal system tracks generic credits, the actual deduction amount varies by operation type. Each service file—such as [`src/server/features/keywords/services/research/research.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/keywords/services/research/research.ts)—specifies a `creditFeature` that maps to specific DataForSEO pricing tiers. Costs typically range from 30 to 100 credits per API call depending on endpoint complexity.