How DataForSEO API Credit Billing Classification Works in OpenSEO

DataForSEO API credit billing classification in OpenSEO maps every API request to a product feature, applies a 28% markup to the raw USD cost, converts it to credits at 1000 credits per dollar, and deducts the amount from the organization's shared monthly and rollover credit pool.

OpenSEO uses DataForSEO as a primary data provider for SEO intelligence. Every API call incurs real costs that must be allocated, tracked, and billed against customer credit balances. The system implements a three-stage classification and metering pipeline that ensures accurate cost attribution while preventing over-spend through built-in credit enforcement.


Mapping Endpoints to Credit Features

The first step in the billing pipeline classifies the API request into a high-level product feature. This abstraction allows customers to understand their spend by capability (e.g., "Backlinks" or "Keyword Research") rather than by raw API endpoint.

The mapDataforseoPathToCreditFeature function in [src/shared/billing-credit-features.ts](https://github.com/every-app/open-seo/blob/main/src/shared/billing-credit-features.ts) (lines 38-71) handles this mapping:

import { mapDataforseoPathToCreditFeature } from "@/shared/billing-credit-features";

const path = ["v3", "backlinks", "summary", "live"];
const feature = mapDataforseoPathToCreditFeature(path);
// feature === "backlinks"

The function returns one of ten CreditFeature enum values:

  • keyword_research
  • domain_overview
  • backlinks
  • site_audit
  • rank_tracking
  • ai_citations
  • ai_prompt_responses
  • local_seo
  • onboarding
  • agent

This classification decouples billing from DataForSEO's internal API versioning, allowing the pricing model to remain stable even when underlying endpoints change.


Metering Calls and Enforcing Credit Availability

Every DataForSEO client method is wrapped by the metering layer implemented in [src/server/lib/dataforseo/client.ts](https://github.com/every-app/open-seo/blob/main/src/server/lib/dataforseo/client.ts) (lines 48-61). The meter function provides:

  1. Pre-flight credit checkassertUsageCreditsAvailable verifies the organization has sufficient usage credits and returns the current monthlyRemaining balance
  2. Actual SDK execution – The wrapped DataForSEO call proceeds only if credits are available
  3. Post-call cost trackingtrackDataforseoCost records the spend using either the auto-derived feature from the path mapping or an explicit creditFeature override

This wrapper ensures no paid API call can execute without credit authorization. In self-hosted mode, these checks may be bypassed, but in hosted mode the enforcement is strict.


Converting Costs and Consuming Credits

The actual credit deduction happens in [src/server/billing/subscription.ts](https://github.com/every-app/open-seo/blob/main/src/server/billing/subscription.ts) (lines 223-288) via the trackUsageCreditSpend function. This implementation follows four precise steps:

1. Apply Platform Markup

Raw DataForSEO costs are multiplied by 28% markup (SEO_DATA_COST_MARKUP = 1.28) and rounded using roundUsdForBilling:

// From src/shared/billing.ts (lines 15-37)
export const SEO_DATA_COST_MARKUP = 1.28;
export const AUTUMN_SEO_DATA_CREDITS_PER_USD = 1000;

2. Convert USD to Credits

The marked-up dollar amount converts to credits at 1000 credits per USD. A $1.25 API call becomes 1,600 credits after markup.

3. Deduct From Balance Pool

Credits are consumed in strict priority order:

  • First: monthlyRemaining usage credits (subscription allowance)
  • Second: topup_credits (rollover or purchased credits)

4. Emit Audit Event

A usage:credits_consume event fires to PostHog for analytics and customer-facing usage dashboards.

When credits are exhausted, checkUsageCreditsDepleted and assertUsageCreditsAvailable block further paid endpoints until the subscription renews or additional credits are purchased.


Manual Credit Charging (Advanced)

While the meter wrapper handles standard cases, direct credit charges are possible through trackUsageCreditSpend:

import { trackUsageCreditSpend } from "@/server/billing/subscription";
import { getOrCreateOrganizationCustomer } from "@/server/billing/subscription";

async function chargeManual(
  ctx: BillingCustomerContext,
  costUsd: number,
  feature: CreditFeature,
) {
  const billingCustomer = await getOrCreateOrganizationCustomer(ctx);
  const { monthlyRemaining } = await assertUsageCreditsAvailable(billingCustomer.id);
  
  await trackUsageCreditSpend({
    customer: ctx,
    customerId: billingCustomer.id,
    creditFeature: feature,
    costUsd,
    monthlyRemaining,
  });
}

This pattern is rarely needed but enables custom integrations or non-standard DataForSEO endpoints not covered by the automatic path mapping.


Key Configuration Constants

Constant Location Value Purpose
SEO_DATA_COST_MARKUP src/shared/billing.ts 1.28 Platform margin multiplier
AUTUMN_SEO_DATA_CREDITS_PER_USD src/shared/billing.ts 1000 USD-to-credit conversion rate
CreditFeature enum src/shared/billing-credit-features.ts 10 variants Product feature taxonomy

Summary

  • Classification: mapDataforseoPathToCreditFeature maps API paths to product features in src/shared/billing-credit-features.ts
  • Metering: The meter wrapper in src/server/lib/dataforseo/client.ts enforces credit availability before every call
  • Cost calculation: Raw USD costs multiply by 1.28, convert at 1000 credits/USD, then deduct from monthly then rollover balances
  • Blocking: Exhausted credit pools trigger assertUsageCreditsAvailable failures that prevent further paid API usage
  • Observability: All consumption emits usage:credits_consume events to PostHog

Frequently Asked Questions

What happens when an organization runs out of credits?

The system blocks further DataForSEO API calls. The assertUsageCreditsAvailable function in src/server/billing/subscription.ts checks balances before every metered request and throws a credit-depleted error if monthlyRemaining and topup_credits are both zero or insufficient.

Can I override the automatic feature classification for a DataForSEO call?

Yes. While the meter function auto-derives features from the API path, callers can supply an explicit creditFeature parameter to override the mapping. This is useful for experimental endpoints or specialized billing treatments not yet in the path-to-feature registry.

How does the 28% markup translate to customer pricing?

DataForSEO reports costs in USD (e.g., $0.005 per 100 results). OpenSEO applies SEO_DATA_COST_MARKUP = 1.28 to cover infrastructure, platform operations, and margin, then converts to credits. Customers see and manage spend in credits rather than raw USD, abstracting provider cost volatility.

Where is the credit conversion rate configured if it needs to change?

The constant AUTUMN_SEO_DATA_CREDITS_PER_USD = 1000 lives in src/shared/billing.ts alongside the markup multiplier. Changing this value affects all future credit calculations but does not retroactively adjust historical transactions, as credits are deducted at call time.

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 →