Skip to content

Billing & Pricing

FOTOhub uses a dual-mode billing system combining prepaid credits with pay-as-you-go wallet fallback. Every API response includes a detailed billing breakdown so you always know exactly what you spent.

Billing Overview

FOTOhub operates on a dual-mode billing system designed for flexibility and cost control:

ModeDescription
CreditsPrepaid monthly allowance included with your plan tier. Credits are deducted first for every operation. Reset monthly on your billing cycle.
Wallet (PLN)Pay-as-you-go fallback when credits are exhausted. Top up your wallet with packages. Charged in PLN with no expiration.
Token-BasedSome models (BytePlus SeedDream, AWS Bedrock) bill per-token instead of a fixed credit cost. Billed after execution based on actual usage.

How Billing Works

The billing flow is evaluated on every request. Here is the complete sequence:

Request → Authentication → Billing Mode Detection

              ┌─────────────────────┴──────────────────────┐
              ↓                                            ↓
     Credit-Based Path                           Token-Based Path
              ↓                                            ↓
   Deduct from monthly                        Execute first, count
   tier allowance                             tokens after completion
              ↓                                            ↓
   Credits exhausted?                         Bill from credits or
      ↓ Yes                                   wallet PLN
   Fall back to wallet PLN                            ↓
              ↓                                            ↓
              └─────────────────────┬──────────────────────┘

                    Response with billing breakdown

Step-by-step:

  1. Authentication — Request comes in and is authenticated via API key. The user's tier and balance are loaded.
  2. Billing Mode Detection — System checks whether the operation uses token-based or credit-based billing based on the model.
  3. Credit-Based Path — Deduct from monthly tier allowance. If credits are exhausted, fall back to wallet PLN automatically.
  4. Token-Based Path — Execute first, count tokens after completion, then bill from credits (if sufficient) or wallet PLN.
  5. Response — Every response includes a full billing breakdown showing method, credits used, and PLN charged.

Automatic Fallback

When your monthly credits are exhausted, billing automatically falls back to your PLN wallet. No configuration needed — as long as your wallet has funds, requests continue without interruption.

The billing Object

Every API response includes a billing field with a complete breakdown of the charges. The structure varies depending on the billing method used.

Credit-based billing

json
{
  "billing": {
    "method": "credits",
    "credits_used": 3,
    "pln_charged": 0.45
  }
}

Token-based billing

json
{
  "billing": {
    "method": "token",
    "credits_used": 2,
    "pln_charged": 0.049,
    "cost_breakdown": {
      "output_tokens": 4096,
      "cost_usd": 0.008192,
      "cost_pln": 0.049152,
      "rate_per_1m_tokens_usd": 2.00
    }
  }
}

Wallet fallback (credits exhausted)

json
{
  "billing": {
    "method": "wallet",
    "credits_used": 0,
    "pln_charged": 0.45
  }
}

Monitoring Costs

Parse the billing object in every response to track your spending in real time. The method field tells you whether you are still using credits or have fallen through to wallet billing.

API Tiers

FOTOhub offers two categories of access tiers:

Pay-As-You-Go (PAYG)

No subscription required. Fund your wallet and pay per operation. Tier upgrades are automatic based on wallet balance and lifetime spending.

TierRequirementsRate LimitModelsFeatures
PAYG BasicRegister + fund wallet30 rpmBasic modelsStandard API access
PAYG StandardMin 100 PLN balance OR 200 PLN lifetime120 rpmAll standardWebhooks, video, music
PAYG PremiumMin 500 PLN balance OR 2,000 PLN lifetime500 rpmAll + betaAgents, batch, compute

Subscription Plans

Monthly subscription with included credit allowance. Overage is charged from wallet at 1.5x provider cost.

PlanMonthly PriceCredits/moRate LimitStorageModels
Developer49 PLN50060 rpm10 GBAll standard
Startup199 PLN5,000300 rpm100 GBAll models
Business799 PLN25,0001,000 rpm500 GBAll + beta
EnterpriseCustomUnlimited5,000 rpmUnlimitedCustom

Tier Endpoints

bash
# Get full tier catalog (no auth required)
curl https://apis.fotohub.app/v1/tiers/catalog

# Get your current tier and usage
curl https://apis.fotohub.app/v1/tiers/current \
  -H "Authorization: Bearer fh_live_your_key"

# Subscribe to a tier
curl -X POST https://apis.fotohub.app/v1/tiers/subscribe \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{"tier": "sub-startup"}'

# Apply for enterprise
curl -X POST https://apis.fotohub.app/v1/tiers/enterprise/apply \
  -H "Authorization: Bearer YOUR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "Acme Corp",
    "contact_email": "[email protected]",
    "company_size": "51-200",
    "use_case": "AI-powered product photography for e-commerce catalog",
    "expected_monthly_volume": "50k images, 5k videos"
  }'

Enterprise Plans

Enterprise plans include dedicated infrastructure, SLA guarantees (custom), priority support, SSO/SAML, and custom rate limits. Submit an application or contact [email protected].

Credit Costs by Operation

Each operation type has a fixed credit cost. For token-based models, credits are calculated dynamically based on actual token usage.

Image Generation

Model IDNameCreditsUnit
imagen-3-fastImagen 3 Fast1per image
imagen-3-standardImagen 3 Standard2per image
imagen-4-fastImagen 4 Fast2per image
imagen-4-standardImagen 4 Standard3per image
imagen-4-ultraImagen 4 Ultra5per image
dall-e-3DALL-E 32per image
dall-e-3-hdDALL-E 3 HD4per image
gpt-image-1GPT Image 14per image
grok-imagine-imageGrok Imagine1per image
grok-imagine-image-proGrok Imagine Pro4per image
flux-2-klein-4bFLUX 2 Klein 4B1per image
flux-2-klein-9bFLUX 2 Klein 9B1per image
flux-2-proFLUX 2 Pro2per image
flux-1.1-proFLUX 1.1 Pro2per image
flux-1.1-pro-ultraFLUX 1.1 Pro Ultra3per image
flux-1.1-pro-rawFLUX 1.1 Pro Raw3per image
flux-kontext-proFLUX Kontext Pro2per image
flux-kontext-maxFLUX Kontext Max4per image
flux-fill-proFLUX Fill Pro3per image
flux-2-maxFLUX 2 Max4per image
minimax-image-01MiniMax Image1per image
kling-v2-1Kling V2.12per image
kling-v3Kling V35per image
kling-v3-omniKling V3 Omni8per image

Video Generation

Credits are multiplied by max(1, duration ÷ 5) for longer clips.

Model IDNameBase Credits (5s)Unit
veo-2Veo 2 (Google)10per 5s segment
veo-3Veo 3 (Google)15per 5s segment
wanWAN8per 5s segment
klingKling Video10per 5s segment
hailuoHailuo (MiniMax)8per 5s segment
seedanceSeedance 2.0 (BytePlus)10per 5s segment
sora-2Sora 2 (OpenAI)12per 5s segment

Video Billing Example

A 30-second video with veo-2 costs: 10 × (30 ÷ 5) = 60 credits. A 5-second clip costs 10 credits.

Music Generation

Model IDNameCreditsUnit
ida-musicIDA Music (≤3 min)2per generation
ida-musicIDA Music (>3 min)4per generation
minimaxMiniMax Music (≤30s)5per generation
minimaxMiniMax Music (≤60s)10per generation
minimaxMiniMax Music (>60s)25per generation

Chat & Analysis

Model IDNameCreditsUnit
gemini-flashGemini Flash1per request
gemini-proGemini Pro2per request
gpt-4oGPT-4o2per request
claude-sonnetClaude Sonnet2per request
image-analysisImage Analysis1per analysis
enhance-promptPrompt Enhancement1per request

Bedrock Chat (Token-Based)

Model IDInput (USD/1M)Output (USD/1M)~PLN/1K tokens
claude-sonnet-4.6$3.00$15.00per-token
claude-sonnet-4.5$3.00$15.00per-token
claude-haiku-4.5$0.80$4.00per-token
nova-pro$0.80$3.20per-token
nova-lite$0.25$1.00per-token
nova-micro$0.10$0.40per-token

Voice & Audio

Model IDNameCreditsUnit
googleIDA Voice (Standard)1per 1000 chars
ida-voiceIDA Voice Pro2per 1000 chars
Sound EffectsSFX Generation3per generation
TranscriptionSpeech-to-Text1per minute
TranslationAudio Translation2per minute
DubbingVoice Dubbing5per minute

3D Generation

ModelNameCreditsUnit
triposrFH Lite 3D5per model
sf3dFH Fast 3D5per model
shap-eFH Text 3D10per model
trellisFH HD 3D15per model
hunyuan3dFH Pro 3D25per model

See 3D Generation for full endpoint reference and output format options (GLB, OBJ, STL, USDZ).

Image Editing & Tools

OperationCreditsUnit
Edit Image (inpaint/outpaint/bgswap/remove/upscale)2per request
Stability Fast Upscale1per image
Stability Remove Background1per image
Stability Style Transfer2per image
Stability Creative Upscale3per image
Stability Inpaint/Outpaint3per image

Token-Based Pricing

Some models bill based on actual token consumption rather than a fixed credit cost. This provides more granular pricing that scales with resolution and complexity.

BytePlus SeedDream

SeedDream models calculate tokens from the output image dimensions. The formula is:

output_tokens = (width × height) / 256
cost_usd = (output_tokens / 1,000,000) × rate_per_1m_usd
cost_pln = cost_usd × 4.0 (USD→PLN) × 1.5 (margin)
ModelRate (USD / 1M tokens)1024×1024 Cost
seedream-5-0-260128$2.000.049 PLN
seedream-4-5-251128$2.500.061 PLN
seedream-4-0-250828$2.000.049 PLN
dola-seedream-5-0-pro-260628$3.500.086 PLN
seededit-3-0-i2i-250628$2.500.061 PLN

PLN Calculation Formula:

cost_pln = (tokens / 1,000,000) x rate_usd x 4.0 x 1.5

The 4.0 is the USD/PLN exchange rate and 1.5 is the platform margin multiplier.

Example: 1024x1024 image with seedream-5-0

tokens = (1024 x 1024) / 256 = 4,096
cost_usd = (4,096 / 1,000,000) x $2.00 = $0.008192
cost_pln = $0.008192 x 4.0 x 1.5 = 0.049 PLN

AWS Bedrock

Bedrock models are billed on actual input + output tokens. Rates are in PLN per 1,000 tokens.

ModelRate (PLN / 1K tokens)Best For
claude-sonnet-4.60.054 PLNComplex reasoning & code
claude-haiku-4.50.015 PLNFast responses & simple tasks
nova-pro0.012 PLNGeneral purpose, cost-effective
nova-lite0.004 PLNHigh-volume, simple tasks
nova-micro0.002 PLNUltra-low-cost classification

Wallet Top-Up Packages

Top up your PLN wallet with packages. Larger packages include bonus credits as a percentage reward.

PackageAmountBonus CreditsBonus %
Starter50 PLN+1000%
Basic100 PLN+2505%
Growth250 PLN+70010%
Pro500 PLN+1,50015%
Scale1,000 PLN+3,50020%
Enterprise5,000 PLN+20,00025%

Bonus Credits

Bonus credits from top-up packages are added to your monthly credit balance and do not expire. They are consumed before wallet PLN.

Hard Spending Limits

Projects can set a hard spending limit (hard_limit_pln) to prevent overspending. Once the limit is reached, all further requests that would charge to the wallet will fail with a 402 Payment Required status.

json
{
  "error": {
    "code": "spending_limit_reached",
    "message": "Hard spending limit of 500.00 PLN reached. Increase your limit or wait for credit reset.",
    "current_spend_pln": 500.00,
    "hard_limit_pln": 500.00,
    "credits_remaining": 0
  }
}

Hard Limits Are Per Billing Cycle

The hard limit tracks total wallet PLN charged in the current billing cycle. It resets when your monthly credits reset. Configure it via your dashboard or the /v1/billing/settings endpoint.

Billing API Endpoints

Use these endpoints to programmatically check your balance, view pricing, and manage your wallet.

GET /v1/billing/balance

Returns your current credit balance and wallet PLN amount.

Authentication: API Key (Bearer token)

Response:

json
{
  "credits": {
    "remaining": 342,
    "total": 5000,
    "resets_at": "2026-08-01T00:00:00Z"
  },
  "wallet": {
    "balance_pln": 127.50,
    "hard_limit_pln": 500.00
  },
  "tier": "startup"
}

GET /v1/billing/pricing

Returns the full pricing catalog for all available models and operations.

Authentication: API Key (Bearer token)

Query Parameters:

ParameterTypeRequiredDescription
categorystringNoFilter by category: image, video, music, chat, voice, analysis
modelstringNoFilter by specific model ID

Response:

json
{
  "models": [
    {
      "id": "flux-pro",
      "category": "image",
      "billing_type": "credits",
      "credits": 4,
      "pln_cost": 0.60,
      "unit": "per image"
    },
    {
      "id": "seedream-5-0",
      "category": "image",
      "billing_type": "token",
      "rate_per_1m_tokens_usd": 2.00,
      "unit": "per image (variable)"
    }
  ]
}

GET /v1/billing/transactions

Returns your billing transaction history with pagination and metadata.

Authentication: API Key (Bearer token)

Query Parameters:

ParameterTypeRequiredDefaultDescription
limitintegerNo50Number of transactions to return (max 100)
offsetintegerNo0Offset for pagination
fromstringNoStart date filter (ISO 8601)
tostringNoEnd date filter (ISO 8601)
typestringNoFilter by type: generation, topup, refund

Response:

json
{
  "transactions": [
    {
      "id": "txn_abc123",
      "type": "generation",
      "method": "credits",
      "credits_used": 4,
      "pln_charged": 0.60,
      "model": "flux-pro",
      "metadata": {
        "tokens": null,
        "resolution": "1024x1024"
      },
      "created_at": "2026-07-17T14:30:00Z"
    },
    {
      "id": "txn_def456",
      "type": "generation",
      "method": "token",
      "credits_used": 0,
      "pln_charged": 0.049,
      "model": "seedream-5-0",
      "metadata": {
        "tokens": 4096,
        "resolution": "1024x1024"
      },
      "created_at": "2026-07-17T14:25:00Z"
    }
  ],
  "total": 1247,
  "has_more": true
}

GET /v1/billing/topup/packages

List available top-up packages with pricing and bonus credits.

Authentication: None required

Response:

json
{
  "packages": [
    {"slug": "topup-50", "amount_pln": 50, "bonus_credits": 100, "bonus_pct": 5},
    {"slug": "topup-100", "amount_pln": 100, "bonus_credits": 250, "bonus_pct": 8},
    {"slug": "topup-250", "amount_pln": 250, "bonus_credits": 700, "bonus_pct": 10},
    {"slug": "topup-500", "amount_pln": 500, "bonus_credits": 1600, "bonus_pct": 12},
    {"slug": "topup-1000", "amount_pln": 1000, "bonus_credits": 3500, "bonus_pct": 15},
    {"slug": "topup-5000", "amount_pln": 5000, "bonus_credits": 20000, "bonus_pct": 20}
  ]
}

POST /v1/billing/topup

Initiate a wallet top-up via Stripe Checkout. Returns a payment URL.

Authentication: JWT (session token)

Request Body:

ParameterTypeRequiredDescription
packagestringYesPackage slug: topup-50, topup-100, topup-250, topup-500, topup-1000, topup-5000

Response:

json
{
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_live_...",
  "package": {
    "slug": "topup-250",
    "amount_pln": 250,
    "bonus_credits": 700,
    "bonus_pct": 10
  }
}

Code Examples

Check Balance

bash
curl -X GET "https://apis.fotohub.app/v1/billing/balance" \
  -H "Authorization: Bearer YOUR_API_KEY"
python
import requests

response = requests.get(
    "https://apis.fotohub.app/v1/billing/balance",
    headers={"Authorization": "Bearer YOUR_API_KEY"}
)

balance = response.json()
print(f"Credits: {balance['credits']['remaining']}/{balance['credits']['total']}")
print(f"Wallet: {balance['wallet']['balance_pln']} PLN")
typescript
const response = await fetch("https://apis.fotohub.app/v1/billing/balance", {
  headers: { "Authorization": "Bearer YOUR_API_KEY" }
});

const balance = await response.json();
console.log(`Credits: ${balance.credits.remaining}/${balance.credits.total}`);
console.log(`Wallet: ${balance.wallet.balance_pln} PLN`);

Get Pricing Catalog

bash
curl -X GET "https://apis.fotohub.app/v1/billing/pricing?category=image" \
  -H "Authorization: Bearer YOUR_API_KEY"
python
import requests

response = requests.get(
    "https://apis.fotohub.app/v1/billing/pricing",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    params={"category": "image"}
)

pricing = response.json()
for model in pricing["models"]:
    if model["billing_type"] == "credits":
        print(f"{model['id']}: {model['credits']} credits ({model['pln_cost']} PLN)")
    else:
        print(f"{model['id']}: token-based @ ${model['rate_per_1m_tokens_usd']}/1M tokens")
typescript
const response = await fetch(
  "https://apis.fotohub.app/v1/billing/pricing?category=image",
  { headers: { "Authorization": "Bearer YOUR_API_KEY" } }
);

const pricing = await response.json();
pricing.models.forEach(model => {
  if (model.billing_type === "credits") {
    console.log(`${model.id}: ${model.credits} credits (${model.pln_cost} PLN)`);
  } else {
    console.log(`${model.id}: token-based @ $${model.rate_per_1m_tokens_usd}/1M tokens`);
  }
});

List Transactions

bash
curl -X GET "https://apis.fotohub.app/v1/billing/transactions?limit=10&from=2026-07-01T00:00:00Z" \
  -H "Authorization: Bearer YOUR_API_KEY"
python
import requests

response = requests.get(
    "https://apis.fotohub.app/v1/billing/transactions",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    params={
        "limit": 10,
        "from": "2026-07-01T00:00:00Z",
        "type": "generation"
    }
)

transactions = response.json()
total_credits = sum(t["credits_used"] for t in transactions["transactions"])
total_pln = sum(t["pln_charged"] for t in transactions["transactions"])
print(f"Last 10 generations: {total_credits} credits, {total_pln:.2f} PLN")
typescript
const params = new URLSearchParams({
  limit: "10",
  from: "2026-07-01T00:00:00Z",
  type: "generation"
});

const response = await fetch(
  `https://apis.fotohub.app/v1/billing/transactions?${params}`,
  { headers: { "Authorization": "Bearer YOUR_API_KEY" } }
);

const { transactions, total } = await response.json();
const totalPln = transactions.reduce((sum, t) => sum + t.pln_charged, 0);
console.log(`Total transactions: ${total}, Recent spend: ${totalPln.toFixed(2)} PLN`);

Top Up Wallet

bash
curl -X POST "https://apis.fotohub.app/v1/billing/topup" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"package": "topup-250"}'
python
import requests

response = requests.post(
    "https://apis.fotohub.app/v1/billing/topup",
    headers={
        "Authorization": "Bearer YOUR_JWT_TOKEN",
        "Content-Type": "application/json"
    },
    json={"package": "topup-250"}
)

result = response.json()
print(f"Checkout URL: {result['checkout_url']}")
print(f"Bonus: +{result['package']['bonus_credits']} credits ({result['package']['bonus_pct']}%)")
typescript
const response = await fetch("https://apis.fotohub.app/v1/billing/topup", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_JWT_TOKEN",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ package: "topup-250" })
});

const result = await response.json();
// Redirect user to complete payment
window.location.href = result.checkout_url;

Webhook Events

Set up webhooks to get notified about billing events:

credits.low

Fired when your credit balance drops below 10% of your tier allowance. Use this to alert your team or trigger an auto top-up.

json
{
  "event": "credits.low",
  "data": {
    "credits_remaining": 45,
    "credits_total": 5000,
    "tier": "startup",
    "percentage_remaining": 0.9
  },
  "timestamp": "2026-07-17T18:00:00Z"
}

credits.depleted

Fired when both credits and wallet are empty. All subsequent requests will receive 402 Payment Required.

json
{
  "event": "credits.depleted",
  "data": {
    "credits_remaining": 0,
    "wallet_balance_pln": 0.00,
    "tier": "startup",
    "last_operation": "flux-pro"
  },
  "timestamp": "2026-07-17T22:15:00Z"
}

billing.charged

Fired whenever a wallet PLN charge occurs (i.e., credits were not sufficient and the wallet was used as fallback).

json
{
  "event": "billing.charged",
  "data": {
    "transaction_id": "txn_abc123",
    "method": "wallet",
    "pln_charged": 0.60,
    "model": "flux-pro",
    "wallet_balance_after": 126.90
  },
  "timestamp": "2026-07-17T14:30:00Z"
}

Webhook Configuration

Configure webhook endpoints in your dashboard under Settings > Webhooks. All webhook payloads are signed with your webhook secret for verification. See the Webhooks documentation for setup details.