package ratelimit import ( "context" "encoding/json" "fmt" "io" "net/http" "time" ) const usageURL = "https://api.anthropic.com/api/oauth/usage" type RateLimit struct { Utilization *float64 `json:"utilization"` // 0-100 ResetsAt *string `json:"resets_at"` // ISO 8601 } type ExtraUsage struct { IsEnabled bool `json:"is_enabled"` MonthlyLimit *float64 `json:"monthly_limit"` UsedCredits *float64 `json:"used_credits"` Utilization *float64 `json:"utilization"` } type UsageResponse struct { FiveHour *RateLimit `json:"five_hour"` SevenDay *RateLimit `json:"seven_day"` SevenDaySonnet *RateLimit `json:"seven_day_sonnet"` ExtraUsage *ExtraUsage `json:"extra_usage"` } func fetchUsage(ctx context.Context, token string) (*UsageResponse, error) { ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() req, err := http.NewRequestWithContext(ctx, http.MethodGet, usageURL, nil) if err != nil { return nil, fmt.Errorf("build request: %w", err) } req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Content-Type", "application/json") req.Header.Set("anthropic-beta", "oauth-2025-04-20") req.Header.Set("User-Agent", "claude-cli/2.1.92") resp, err := http.DefaultClient.Do(req) if err != nil { return nil, fmt.Errorf("request: %w", err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("usage returned %d: %s", resp.StatusCode, string(body)) } var usage UsageResponse if err := json.Unmarshal(body, &usage); err != nil { return nil, fmt.Errorf("decode: %w", err) } return &usage, nil }