On this page
Reference
TypeScript types
Copy-ready types for the responses used across the dashboard.
These are the same shapes the dashboard uses. They are intentionally permissive where the backend can return provider-specific values.
export type Micro = number; // 1_000_000 = $1
export interface TokenResponse { token: string; user_id: string;}
export interface Me { id: string; email: string; created_at: number; email_verified: boolean; role: 'user' | 'admin'; is_admin: boolean; balance_micro: Micro; balance_usd: number; network_fee_micro: number; // -1 = model default, 0 = waived, >0 = custom}
export interface KeyResponse { id: string; name: string; prefix: string; created_at: number; expires_at: number | null; rpm_limit: number; conc_limit: number; daily_cap_micro: Micro; monthly_cap_micro: Micro; allow_fallback: boolean; byok_provider: string | null; byok_base_url: string | null; key: string | null; // only on create/rotate}
export interface ModelPricing { prompt: number; // USD / 1M (billed) completion: number; // USD / 1M (billed) token_multiplier: number; fixed_micro: Micro; image_micro: Micro; audio_min_micro: Micro; video_sec_micro: Micro; official_prompt: number; // upstream reference (0 = unknown) official_completion: number; discount_pct: number; // configured discount (0-100) discount_fiat_micro: Micro;// flat micro-USD per 1M tokens removed saved_pct: number; // effective saving for badges}
export interface Model { id: string; name: string; created: number; description: string; modality: string; supports_cache: boolean; context_length: number; max_output_tokens: number; is_free: boolean; discounted: boolean; discount_pct: number; saved_pct: number; pricing: ModelPricing;}
export interface AdminUser { id: string; email: string; created_at: number; balance_micro: Micro; keys: number; verified: boolean; role: 'user' | 'admin' | string; token_limit: number; tokens_used: number; token_multiplier: number; allowed_models_count: number; // 0 = every public model network_fee_micro: number;}
export interface AccountLimits { user_id: string; balance_micro: Micro; balance_usd: number; token_limit: number; tokens_used: number; tokens_remaining: number; // -1 = unlimited token_multiplier: number; allowed_models: string[]; price_overrides: Record<string, [number, number]>; network_fee_micro: number; daily_model_caps: Array<{ model: string; name: string; input: { limit: number; used: number; remaining: number }; output: { limit: number; used: number; remaining: number }; resets_at: number; }>;}
export interface EmailPrefs { security: boolean; usage: boolean; news: boolean; promotions: boolean;}
export interface AccountSettings { auto_fallback: boolean; email_prefs: EmailPrefs;}
export interface AdminModelUsage { model: string; days: number; totals: { requests: number; prompt_tokens: number; completion_tokens: number; total_tokens: number; cost_micro: Micro; cost_usd: number; accounts: number; }; per_day: Array<{ day: number; requests: number; prompt_tokens: number; completion_tokens: number; cost_micro: Micro; }>; top_users: Array<{ user_id: string; email: string; requests: number; cost_micro: Micro; }>;}
export interface AdminUserLimits { user_id: string; email: string; role: string; balance_micro: Micro; balance_usd: number; token_limit: number; tokens_used: number; token_multiplier: number; allowed_models: string[]; price_overrides: Record<string, [number, number]>; network_fee_micro: number;}
export interface UsageResponse { days: number; balance_micro: Micro; balance_usd: number; totals: { requests: number; prompt_tokens: number; completion_tokens: number; cost_micro: Micro; cost_usd: number; }; per_day: Array<{ day: number; requests: number; prompt_tokens: number; completion_tokens: number; cost_micro: Micro; }>; by_model: Array<{ model: string; requests: number; prompt_tokens: number; completion_tokens: number; cost_micro: Micro; }>;}
export interface Deposit { id: string; amount_usd: number; status: "pending" | "paying" | "completed" | "failed" | "expired" | string; track_id: string | null; payment_url: string | null; created_at: number;}
export interface Receipt { receipt_no: string; amount_usd: number; paid_at: number; created_at: number; track_id: string | null; url: string;}
export interface ReceiptDetail { receipt_no: string; billed_to: string; description: string; amount_usd: number; currency: "USD"; status: "paid"; paid_at: number; created_at: number; issuer: string;}
export interface NewsItem { id: string; title: string; body: string; created_at: number; updated_at: number;}
export interface StatusSnapshot { status: "operational" | "degraded" | string; service: string; version: string; time: number; uptime_seconds: number; uptime_human: string; components: Record<string, { status: string }>; models: { enabled: number; free: number }; news: Array<{ title: string; body: string; created_at: number }>;}
export interface ChatUsage { prompt_tokens: number; completion_tokens: number; total_tokens: number; prompt_cache_hit_tokens?: number; prompt_cache_miss_tokens?: number; prompt_cache_write_tokens?: number; cache_read_input_tokens?: number; cache_creation_input_tokens?: number; cached_tokens?: number; completion_thinking_tokens?: number; completion_tokens_details?: { reasoning_tokens?: number }; cost?: number; // provider-reported, not RelayRouter's charge}
export interface ChatCompletion { id: string; object: "chat.completion"; created: number; model: string; choices: Array<{ index: number; finish_reason: string | null; message: { role: "assistant"; content: string | null; reasoning_content?: string; tool_calls?: unknown[]; }; }>; usage: ChatUsage;}The project's own copy of these types lives in
lib/types.ts and includes a few additional fields used by the UI.