An r/SideProject user was tired of paying $29+ monthly for SEO tools they barely used. This tutorial builds a thin API layer that wraps Scavio, tracks per-query costs, and lets you (or your users) see exact usage. Think of it as a metered SEO API you control.
Prerequisites
- Scavio API key
- Python 3.8+ with Flask or FastAPI
- SQLite for usage tracking
Walkthrough
Step 1: Set up the API server
Minimal FastAPI app that proxies to Scavio with usage tracking.
from fastapi import FastAPI, Header, HTTPException
from pydantic import BaseModel
import requests, os, sqlite3, datetime
app = FastAPI()
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
conn = sqlite3.connect('usage.db', check_same_thread=False)
conn.execute('CREATE TABLE IF NOT EXISTS usage (ts TEXT, user TEXT, query TEXT, cost REAL)')
class SearchRequest(BaseModel):
query: str
country_code: str = 'us'Step 2: Proxy search requests with cost tracking
Each request logs the cost.
@app.post('/seo/rank-check')
async def rank_check(req: SearchRequest, x_user: str = Header()):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=H,
json={'platform': 'google', 'query': req.query,
'country_code': req.country_code}).json()
# Log usage: $0.005 per query
conn.execute('INSERT INTO usage VALUES (?, ?, ?, ?)',
(datetime.datetime.now().isoformat(), x_user, req.query, 0.005))
conn.commit()
return {'results': data.get('organic_results', []), 'cost': 0.005}Step 3: Add usage dashboard endpoint
Let users see their usage and costs.
@app.get('/usage/{user}')
async def get_usage(user: str):
rows = conn.execute(
'SELECT date(ts) as day, count(*) as queries, sum(cost) as total '
'FROM usage WHERE user=? GROUP BY date(ts) ORDER BY day DESC LIMIT 30',
(user,)).fetchall()
return {'user': user,
'daily_usage': [{'date': r[0], 'queries': r[1], 'cost': r[2]} for r in rows],
'total_cost': sum(r[2] for r in rows)}Step 4: Add budget limits
Prevent users from exceeding a monthly budget.
@app.post('/seo/rank-check-metered')
async def rank_check_metered(req: SearchRequest, x_user: str = Header()):
monthly_spend = conn.execute(
'SELECT sum(cost) FROM usage WHERE user=? AND ts >= date("now", "start of month")',
(x_user,)).fetchone()[0] or 0
budget = 5.00 # $5/month default budget
if monthly_spend >= budget:
raise HTTPException(429, f'Monthly budget of ${budget} exceeded. Current: ${monthly_spend:.2f}')
return await rank_check(req, x_user)Python Example
# Self-hosted metered SEO API:
# $0.005 per rank check via Scavio
# SQLite tracks per-user usage
# Budget limits prevent overuse
# 100 queries/month = $0.50 vs $29+ for Ahrefs StarterJavaScript Example
// Express.js equivalent:
app.post('/seo/rank-check', async (req, res) => {
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'},
body: JSON.stringify({platform: 'google', query: req.body.query})
}).then(r => r.json());
// log usage to DB
res.json({results: data.organic_results, cost: 0.005});
});Expected Output
Self-hosted metered SEO API with per-query cost tracking, usage dashboard, and budget limits. 100 queries/month = $0.50 vs Ahrefs Starter at $29/mo.