/ docs / 07-integrations / openrouter-credits.md
openrouter-credits.md
  1  ---
  2  title: OpenRouter Credit Monitoring
  3  category: 07-integrations
  4  last_verified: 2026-02-16
  5  related_files:
  6    - src/utils/openrouter-monitor.js
  7    - src/cron/monitor-openrouter-credits.js
  8    - db/migrations/055-create-openrouter-credit-log.sql
  9    - tests/openrouter-monitor.test.js
 10  tags: [openrouter, monitoring, credits, alerting, api]
 11  status: active
 12  ---
 13  
 14  # OpenRouter Credit Monitoring
 15  
 16  Monitor OpenRouter API credit balance and usage to prevent service disruption from depleted credits.
 17  
 18  ## Overview
 19  
 20  The OpenRouter credit monitoring system provides:
 21  
 22  - **Real-time balance checks** via OpenRouter API
 23  - **Historical tracking** in SQLite database
 24  - **Burn rate calculation** (7-day average)
 25  - **Forecasting** days until credit exhaustion
 26  - **Threshold alerting** (warning/critical levels)
 27  - **CLI access** for on-demand checks
 28  - **Cron scheduling** for periodic monitoring
 29  
 30  ## Quick Start
 31  
 32  ### Check Credits On-Demand
 33  
 34  ```bash
 35  # Basic check
 36  npm run credits
 37  
 38  # Verbose output (includes rate limits)
 39  npm run credits:verbose
 40  
 41  # Custom threshold
 42  node src/utils/openrouter-monitor.js --threshold=25.0
 43  ```
 44  
 45  ### Example Output
 46  
 47  ```
 48  Checking OpenRouter credits...
 49  
 50  API Key: Production Key
 51  Balance: $45.23 remaining
 52  Usage: $54.77 / $100.00
 53  
 54  Burn Rate: $3.21/day (7-day average)
 55  Days Left: 14.1 days at current rate
 56  
 57  ✓ Credits OK
 58  ```
 59  
 60  ## Configuration
 61  
 62  ### Environment Variables
 63  
 64  Add to `.env`:
 65  
 66  ```bash
 67  # OpenRouter API key (required)
 68  OPENROUTER_API_KEY=your_key_here
 69  
 70  # Alert threshold in USD (default: $10)
 71  OPENROUTER_CREDIT_THRESHOLD=10.0
 72  ```
 73  
 74  ### Alert Thresholds
 75  
 76  - **Warning**: Credits < threshold
 77  - **Critical**: Credits exhausted (≤ $0)
 78  
 79  Customize threshold based on your burn rate and refill workflow.
 80  
 81  ## Database Schema
 82  
 83  The `openrouter_credit_log` table tracks historical balance:
 84  
 85  ```sql
 86  CREATE TABLE openrouter_credit_log (
 87    id INTEGER PRIMARY KEY AUTOINCREMENT,
 88    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
 89  
 90    -- Key info
 91    label TEXT,                    -- API key label
 92  
 93    -- Credit balance
 94    usage REAL NOT NULL,           -- Total spend ($)
 95    credit_limit REAL,             -- Credit limit ($)
 96    remaining REAL,                -- Calculated remaining
 97    is_free_tier INTEGER,          -- 1 if free tier
 98  
 99    -- Rate limiting
100    rate_limit TEXT,               -- JSON string
101  
102    -- Raw API response
103    raw_response TEXT
104  );
105  ```
106  
107  ## API Integration
108  
109  The monitoring system calls OpenRouter's auth endpoint:
110  
111  ```javascript
112  GET https://openrouter.ai/api/v1/auth/key
113  Headers:
114    Authorization: Bearer {OPENROUTER_API_KEY}
115    HTTP-Referer: https://333method.local
116    X-Title: 333 Method Automation
117  
118  Response:
119  {
120    "data": {
121      "label": "Production Key",
122      "usage": 54.77,
123      "limit": 100.0,
124      "is_free_tier": false,
125      "rate_limit": {
126        "requests": 200,
127        "interval": "10s"
128      }
129    }
130  }
131  ```
132  
133  ## Programmatic Usage
134  
135  ```javascript
136  import {
137    checkCredits,
138    getRemainingCredits,
139    checkThreshold,
140    monitorCredits,
141    displayCredits,
142  } from './src/utils/openrouter-monitor.js';
143  
144  // Full monitoring with database logging
145  const status = await monitorCredits({ threshold: 10.0 });
146  console.log(status);
147  // {
148  //   remaining: 45.23,
149  //   alert: null,
150  //   burnRate: 3.21,
151  //   daysLeft: 14.1,
152  //   keyInfo: { ... }
153  // }
154  
155  // Check for alerts
156  if (status.alert) {
157    console.error(`${status.alert.level}: ${status.alert.message}`);
158    // Send notification
159  }
160  
161  // CLI-friendly display
162  await displayCredits({ threshold: 10.0, verbose: true });
163  ```
164  
165  ## Automated Monitoring
166  
167  ### Cron Job
168  
169  The monitoring cron runs every 6 hours:
170  
171  ```bash
172  # Manual trigger
173  npm run credits:monitor
174  
175  # View logs
176  grep 'monitor-openrouter-credits' logs/cron-*.log
177  ```
178  
179  ### Cron Configuration
180  
181  Add to cron tasks table (automated in future release):
182  
183  ```sql
184  INSERT INTO cron_tasks (name, schedule, command, enabled) VALUES (
185    'monitor-openrouter-credits',
186    '0 */6 * * *',  -- Every 6 hours
187    'npm run credits:monitor',
188    1
189  );
190  ```
191  
192  ### Alert Actions
193  
194  When credits drop below threshold, the cron job:
195  
196  1. Logs error to console/logs
197  2. Records event in database
198  3. (Future) Sends notification via configured channel:
199     - Email alert to admin
200     - Slack/Discord webhook
201     - SMS alert
202     - Create agent task to investigate
203  
204  ## Burn Rate Analysis
205  
206  ### Daily Burn Rate
207  
208  Calculated from 7-day usage history:
209  
210  ```javascript
211  import { getDailyBurnRate } from './src/utils/openrouter-monitor.js';
212  
213  const burnRate = getDailyBurnRate(7); // 7-day average
214  console.log(`$${burnRate.toFixed(2)}/day`);
215  ```
216  
217  ### Days Until Exhaustion
218  
219  Forecast when credits will run out:
220  
221  ```javascript
222  import { getDaysUntilExhaustion } from './src/utils/openrouter-monitor.js';
223  
224  const days = getDaysUntilExhaustion(remaining, 7);
225  console.log(`${days.toFixed(1)} days left`);
226  ```
227  
228  ### Credit History
229  
230  Query historical balance:
231  
232  ```javascript
233  import { getCreditHistory } from './src/utils/openrouter-monitor.js';
234  
235  const history = getCreditHistory(30); // Last 30 days
236  history.forEach(entry => {
237    console.log(`${entry.timestamp}: $${entry.remaining} remaining`);
238  });
239  ```
240  
241  ## Dashboard Integration
242  
243  The credit monitor data is available in the Dashboard:
244  
245  - **System Health page**: Current balance widget
246  - **Financial page**: Burn rate chart, 30-day history
247  - **Alerts page**: Low credit warnings
248  
249  ## Cost Optimization
250  
251  ### Reduce OpenRouter Usage
252  
253  1. **Use Anthropic API directly** for pipeline stages:
254  
255     ```bash
256     ANTHROPIC_API_KEY=your_key
257     # OpenRouter falls back only if Anthropic not set
258     ```
259  
260  2. **Enable HTML-only analysis** (63% cost reduction):
261  
262     ```bash
263     USE_COMPUTER_VISION_SCORING=false
264     USE_COMPUTER_VISION_RESCORING=false
265     ```
266  
267  3. **Use cheaper models** for non-vision tasks:
268  
269     ```bash
270     CLASSIFICATION_MODEL=anthropic/claude-3.5-haiku  # $0.80/$4 vs $3/$15
271     ```
272  
273  4. **Monitor LLM usage** by stage:
274     ```sql
275     SELECT stage, SUM(estimated_cost) as cost, COUNT(*) as calls
276     FROM llm_usage
277     WHERE created_at > datetime('now', '-7 days')
278     GROUP BY stage
279     ORDER BY cost DESC;
280     ```
281  
282  ## Troubleshooting
283  
284  ### "OPENROUTER_API_KEY not set"
285  
286  Add key to `.env`:
287  
288  ```bash
289  OPENROUTER_API_KEY=sk-or-v1-...
290  ```
291  
292  ### "OpenRouter API error (401)"
293  
294  API key invalid or expired. Get new key from https://openrouter.ai/keys
295  
296  ### "OpenRouter API error (502)"
297  
298  Authentication service down. Retry after a few minutes.
299  
300  ### "no such table: openrouter_credit_log"
301  
302  Run database migration:
303  
304  ```bash
305  npm run db-migrate
306  ```
307  
308  Or manually:
309  
310  ```bash
311  sqlite3 db/sites.db < db/migrations/055-create-openrouter-credit-log.sql
312  ```
313  
314  ### Burn rate shows null
315  
316  Insufficient history (need 2+ entries). Check again after cron runs.
317  
318  ## Testing
319  
320  ### Unit Tests
321  
322  ```bash
323  node --test tests/openrouter-monitor.test.js
324  ```
325  
326  ### Integration Test
327  
328  Test with real API key:
329  
330  ```bash
331  # Set API key in .env
332  OPENROUTER_API_KEY=sk-or-v1-...
333  
334  # Check credits
335  npm run credits:verbose
336  ```
337  
338  ## Security
339  
340  ### API Key Protection
341  
342  - Never commit `.env` file
343  - Use environment variables in production
344  - Rotate keys periodically
345  - Use separate keys for dev/prod
346  
347  ### Rate Limiting
348  
349  OpenRouter enforces rate limits per key. The monitor:
350  
351  - Logs rate limit info to database
352  - Respects API timeout (30s)
353  - Fails gracefully on errors
354  
355  ## Future Enhancements
356  
357  ### Planned Features
358  
359  1. **Multi-channel alerting**:
360     - Email notifications
361     - Slack/Discord webhooks
362     - SMS alerts for critical
363  
364  2. **Auto-refill integration**:
365     - Trigger payment when low
366     - Coinbase crypto payments
367     - Credit card auto-charge
368  
369  3. **Cost forecasting**:
370     - Predict monthly spend
371     - Budget tracking
372     - Anomaly detection
373  
374  4. **Agent integration**:
375     - Auto-create agent tasks for low credits
376     - Investigate usage spikes
377     - Optimize model selection
378  
379  ## Related Documentation
380  
381  - [LLM Provider Abstraction](../02-architecture/llm-provider.md)
382  - [LLM Usage Tracking](../08-operations/llm-usage-tracking.md)
383  - [Cron System](../06-automation/cron-system.md)
384  - [System Health Dashboard](./dashboard.md)
385  
386  ## See Also
387  
388  - OpenRouter Docs: https://openrouter.ai/docs
389  - OpenRouter Keys: https://openrouter.ai/keys
390  - OpenRouter Models: https://openrouter.ai/docs#models