Use the activity and credits endpoints to monitor DA spend, set alerts, and cut usage before you run out of balance.
The activity API gives you daily visibility into your token usage and DA spend. This recipe shows how to query the API, detect spending spikes, and build automated cost controls.
Both endpoints are key-authed inference routes (Authorization: Bearer $OPENDUNES_API_KEY):
| Endpoint | Description |
|---|---|
GET /v1/activity | Daily usage rolled up per model — tokens, requests, DA spend |
GET /v1/credits | Lifetime DA totals — deposited and spent |
For request-level logs and CSV/JSON export, use Dashboard → Analytics or the activity export.
# Last 30 days, one row per day and model
curl "https://opendunes.com/v1/activity" \
-H "Authorization: Bearer $OPENDUNES_API_KEY"{
"data": [
{
"date": "2026-06-30",
"model": "anthropic/claude-opus-4.8",
"model_permaslug": "anthropic/claude-opus-4.8",
"endpoint_id": "a223cc6b-19a9-48ac-a297-3210a86073e5",
"provider_name": "anthropic",
"prompt_tokens": 482000,
"completion_tokens": 123000,
"requests": 1245,
"usage": 184.23
}
]
}usage is the DA spent that day on that model. Pass ?date=YYYY-MM-DD to narrow to a single day.
The rows arrive grouped per day × model, so a per-model breakdown is a small aggregation:
import os, requests
from collections import defaultdict
BASE = "https://opendunes.com"
HEADERS = {"Authorization": f"Bearer {os.environ['OPENDUNES_API_KEY']}"}
rows = requests.get(f"{BASE}/v1/activity", headers=HEADERS).json()["data"]
by_model = defaultdict(float)
for r in rows:
by_model[r["model"]] += r["usage"]
for model, da in sorted(by_model.items(), key=lambda x: -x[1]):
print(f"{model}: {da:.2f} DA")This breakdown tells you which models are driving most of your spend — often the starting point for optimization.
def check_daily_spend(threshold_da: float) -> None:
from datetime import date
resp = requests.get(
f"{BASE}/v1/activity",
params={"date": date.today().isoformat()},
headers=HEADERS,
)
resp.raise_for_status()
total = sum(r["usage"] for r in resp.json()["data"])
if total > threshold_da:
send_alert(f"Spend spike: {total:.2f} DA so far today")
def send_alert(message: str) -> None:
# Send to Slack, email, PagerDuty, etc.
print(f"ALERT: {message}")
# Run this on a cron every hour
check_daily_spend(threshold_da=100.0)curl https://opendunes.com/v1/credits \
-H "Authorization: Bearer $OPENDUNES_API_KEY"{
"data": {
"total_credits": 5000,
"total_usage": 4575
}
}The remaining balance is total_credits - total_usage (DA). The X-Balance-Available header on every inference response also returns the current balance in micro-DA — useful for inline checks without a separate API call.
def balance_da() -> float:
r = requests.get(f"{BASE}/v1/credits", headers=HEADERS)
r.raise_for_status()
data = r.json()["data"]
return data["total_credits"] - data["total_usage"]
LOW_BALANCE_THRESHOLD_DA = 50.0
if balance_da() < LOW_BALANCE_THRESHOLD_DA:
# Pause job queue, alert on-call, redirect to a cheaper model tier
pause_inference_queue()
send_alert(f"Balance below {LOW_BALANCE_THRESHOLD_DA} DA — topping up required.")max_tokens caps — set a realistic max_tokens per request type; runaway generations can multiply expected cost by 5–10×.