merge: chore/cleanup-remove-bloat-and-secrets into main
This commit is contained in:
commit
bde2f3a97d
1173 changed files with 437609 additions and 0 deletions
96
app/routers/dev_portal.py
Normal file
96
app/routers/dev_portal.py
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
"""API Developer Portal — self-service key management, docs, usage tracking."""
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from fastapi import APIRouter, Header, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
router = APIRouter(prefix="/api/v1/developer", tags=["developer-portal"])
|
||||
|
||||
# In-memory store (Supabase in prod)
|
||||
_api_keys: dict[str, dict] = {}
|
||||
_usage_store: dict[str, list] = {}
|
||||
|
||||
|
||||
class CreateKeyRequest(BaseModel):
|
||||
email: str
|
||||
name: str = ""
|
||||
|
||||
|
||||
class APIKeyResponse(BaseModel):
|
||||
key: str
|
||||
name: str
|
||||
email: str
|
||||
tier: str = "free"
|
||||
created_at: str
|
||||
requests_today: int = 0
|
||||
|
||||
|
||||
def _generate_key() -> str:
|
||||
return "rmi_" + hashlib.sha256(os.urandom(32)).hexdigest()[:32]
|
||||
|
||||
|
||||
@router.post("/keys")
|
||||
async def create_api_key(req: CreateKeyRequest):
|
||||
"""Generate a new API key. Free tier: 100 requests/day."""
|
||||
key = _generate_key()
|
||||
_api_keys[key] = {
|
||||
"key": key,
|
||||
"name": req.name or "Untitled",
|
||||
"email": req.email,
|
||||
"tier": "free",
|
||||
"created_at": datetime.now(UTC).isoformat(),
|
||||
"requests_today": 0,
|
||||
}
|
||||
return APIKeyResponse(**_api_keys[key])
|
||||
|
||||
|
||||
@router.get("/keys")
|
||||
async def list_keys(x_api_key: str = Header(...)):
|
||||
"""List your API keys."""
|
||||
if x_api_key not in _api_keys:
|
||||
raise HTTPException(401, "Invalid API key")
|
||||
return {"keys": [_api_keys[x_api_key]]}
|
||||
|
||||
|
||||
@router.delete("/keys/{key}")
|
||||
async def revoke_key(key: str):
|
||||
"""Revoke an API key."""
|
||||
_api_keys.pop(key, None)
|
||||
return {"revoked": key}
|
||||
|
||||
|
||||
@router.get("/usage")
|
||||
async def get_usage(x_api_key: str = Header(...)):
|
||||
"""Get your API usage stats."""
|
||||
if x_api_key not in _api_keys:
|
||||
raise HTTPException(401, "Invalid API key")
|
||||
return {
|
||||
"key": x_api_key,
|
||||
"tier": _api_keys[x_api_key]["tier"],
|
||||
"requests_today": _api_keys[x_api_key].get("requests_today", 0),
|
||||
"limit": 100 if _api_keys[x_api_key]["tier"] == "free" else 10000,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/docs")
|
||||
async def api_docs():
|
||||
"""API documentation — available endpoints."""
|
||||
return {
|
||||
"base_url": "https://rugmunch.io/api/v1",
|
||||
"authentication": "X-API-Key header",
|
||||
"rate_limits": {"free": "100/day", "pro": "10,000/day", "enterprise": "unlimited"},
|
||||
"endpoints": [
|
||||
{"method": "GET", "path": "/databus/fetch/{data_type}", "desc": "Query DataBus"},
|
||||
{"method": "GET", "path": "/token/scan", "desc": "SENTINEL security scan"},
|
||||
{"method": "GET", "path": "/mev-sniper/signals", "desc": "MEV sniper signals"},
|
||||
{"method": "GET", "path": "/sentiment/token/{symbol}", "desc": "Social sentiment"},
|
||||
{"method": "GET", "path": "/arbitrage/find/{symbol}", "desc": "Cross-chain arbitrage"},
|
||||
{"method": "GET", "path": "/prediction-markets/markets", "desc": "Prediction markets"},
|
||||
{"method": "GET", "path": "/dify-tools/catalog", "desc": "All 15 AI tools"},
|
||||
],
|
||||
"sdks": ["Python: pip install rmi-sdk (coming soon)", "JavaScript: npm install rmi-sdk (coming soon)"],
|
||||
"swagger": "https://rugmunch.io/docs",
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue