How OpenSEO's Billing Credit System and Markup Calculation Works

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. The helper function autumnSeoDataCreditsToUsd performs this calculation using the constant AUTUMN_SEO_DATA_CREDITS_PER_USD:

// 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, 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%):

// 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 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 Implements subscription logic, credit-to-USD conversion, and markup application during invoicing.
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 Demonstrates creditFeature: "keyword_research" assignment for credit costing.
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.
  • 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. 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. 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—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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →