---
title: Running Out of Credits
sidebar_position: 7
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
You've run out of credits or are running low, and you're probably confused about why. The most common reason is a misunderstanding about how credits work: **1 request does not always equal 1 credit**. This guide will help you understand what happened, why it happened, and what you can do about it.
For complete details on rate limits and credits, see our [Rate Limits documentation](/api/rate-limiting.md).
## Understanding What Happened: Why 1 Request ≠ 1 Credit
The core issue that likely caused your problem is that **bulk endpoints consume multiple credits** when they return data for multiple symbols. Here's how credit consumption actually works:
### Standard Requests
- **1 request = 1 credit** (most endpoints)
### Bulk Endpoints with Quote Data
- **1 request = N credits** (where N = number of symbols with bid/ask/mid/last)
- `options/chain` endpoint
- `stocks/quotes` endpoint (when requesting multiple symbols)
- `stocks/prices` endpoint (when requesting multiple symbols)
- `stocks/bulkcandles` endpoint
### Bulk Endpoints without Quote Columns
- **1 request = 1 credit** (even with multiple symbols)
- This applies when you exclude `bid`, `ask`, `mid`, and `last` columns from your request
### Other Credit Rules
- **Candles**: 1 credit per 1,000 candles
- **Special cases**: Free trial symbols (AAPL) don't consume credits
### Examples of What Likely Happened
**Example 1: Option Chain Request**
```http
GET https://api.marketdata.app/v1/options/chain/SPX/?expiration=all
```
- **Result**: 20,000+ credits consumed in ONE request
- **Why**: SPX option chain contains 20,000+ option symbols, and each symbol with quote data = 1 credit
**Example 2: Bulk Stock Quotes**
```http
GET https://api.marketdata.app/v1/stocks/quotes/?symbols=AAPL,META,MSFT,GOOGL,AMZN
```
- **With quote data (bid/ask/mid/last)**: 5 credits consumed (1 per symbol)
- **Without quote columns**: 1 credit consumed (regardless of symbol count)
**Example 3: Bulk Stock Prices**
```http
GET https://api.marketdata.app/v1/stocks/prices/?symbols=AAPL,META,MSFT,GOOGL,AMZN
```
- **With quote data**: 5 credits consumed (1 per symbol)
- **Without quote columns**: 1 credit consumed
## Diagnosing Your Credit Usage
To figure out what caused your credit depletion, you need to check your recent API requests and their response headers.
### Check the Rate Limit Headers
Every API response includes headers that show your credit usage. These are the key headers to check:
- **`X-Api-Ratelimit-Consumed`**: Shows how many credits your last request used (KEY for diagnosis)
- **`X-Api-Ratelimit-Remaining`**: Shows how many credits you have left
- **`X-Api-Ratelimit-Limit`**: Shows your plan's limit
- **`X-Api-Ratelimit-Reset`**: Shows when credits reset (UTC epoch seconds)
### How to Check Headers
```bash
curl -i -X GET "https://api.marketdata.app/v1/stocks/quotes/AAPL/" \
-H "Authorization: Bearer YOUR_TOKEN"
```
```python
from marketdata.client import MarketDataClient
client = MarketDataClient()
quotes = client.stocks.quotes("AAPL")
# Check credit consumption
rate_limits = client.rate_limits
print(f"Credits consumed: {rate_limits.requests_consumed}")
print(f"Credits remaining: {rate_limits.requests_remaining}")
print(f"Credit limit: {rate_limits.requests_limit}")
```
```javascript
const response = await fetch(
"https://api.marketdata.app/v1/stocks/quotes/AAPL/",
{
headers: {
"Authorization": "Bearer YOUR_TOKEN"
}
}
);
const consumed = response.headers.get('X-Api-Ratelimit-Consumed');
const remaining = response.headers.get('X-Api-Ratelimit-Remaining');
const limit = response.headers.get('X-Api-Ratelimit-Limit');
console.log(`Credits consumed: ${consumed}`);
console.log(`Credits remaining: ${remaining}`);
console.log(`Credit limit: ${limit}`);
```
### Common Causes of Unexpected Credit Depletion
**1. Option Chain Requests**
- Requesting entire chains without filtering (most common issue)
- A single SPX option chain request can consume 20,000+ credits
**2. Bulk Stock Requests**
- Using `stocks/quotes` or `stocks/prices` with many symbols and quote data included
- Each symbol in the response = 1 credit
**3. Repeated Expensive Requests**
- Making the same expensive request multiple times
- Not caching responses in your application
**4. Not Using Cached Mode**
- Always requesting live data when cached would suffice
- Cached mode costs 1 credit per request regardless of symbol count
**5. Including Unnecessary Columns**
- Requesting `bid`, `ask`, `mid`, `last` columns when not needed
- These columns trigger per-symbol credit consumption
**6. Misunderstanding Reset Time**
- Credits reset at 9:30 AM ET, not midnight
- This can cause confusion about when credits will be available again
## What to Do Right Now
### If You're Out of Credits
**When Credits Reset:**
- Credits reset at **9:30 AM Eastern Time** (NYSE opening bell)
- You'll need to wait until the reset time
- Use `America/New_York` timezone to calculate when your credits will reset
- Check the `X-Api-Ratelimit-Reset` header for the exact reset time (UTC epoch seconds)
**Calculate Reset Time:**
```python
from datetime import datetime
import pytz
# Get reset time from header (UTC epoch seconds)
reset_epoch = int(response.headers.get('X-Api-Ratelimit-Reset'))
reset_time = datetime.fromtimestamp(reset_epoch, tz=pytz.UTC)
eastern = pytz.timezone('America/New_York')
reset_local = reset_time.astimezone(eastern)
print(f"Credits reset at: {reset_local.strftime('%Y-%m-%d %I:%M %p %Z')}")
```
```javascript
// Get reset time from header (UTC epoch seconds)
const resetEpoch = parseInt(response.headers.get('X-Api-Ratelimit-Reset'));
const resetDate = new Date(resetEpoch * 1000); // Convert to milliseconds
// Convert to Eastern Time
const resetLocal = resetDate.toLocaleString('en-US', {
timeZone: 'America/New_York',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: true
});
console.log(`Credits reset at: ${resetLocal}`);
```
### If You Have Credits Remaining
1. **Check your remaining credits** using the `X-Api-Ratelimit-Remaining` header
2. **Review recent requests** to identify which ones consumed the most credits
3. **Check the `X-Api-Ratelimit-Consumed` header** from your recent requests
4. **Implement fixes** before you run out completely (see strategies below)
## How to Prevent This From Happening Again
### A. Use Cached Mode (Paid Plans Only)
Cached mode is the most effective way to reduce credit usage for bulk data requests. With cached mode, you pay **1 credit per request** regardless of how many symbols are in the response.
**How it works:**
- Use `mode=cached` parameter on supported endpoints
- Works with: `options/chain`, `stocks/quotes`, `stocks/prices`
- Returns recently cached data (may be seconds to minutes old)
- Best for bulk quote retrieval when real-time data isn't critical
**Example:**
```http
# Without cached mode: 20,000+ credits
GET https://api.marketdata.app/v1/options/chain/SPX/?expiration=all
# With cached mode: 1 credit
GET https://api.marketdata.app/v1/options/chain/SPX/?mode=cached
```
For more details, see the [mode parameter documentation](/api/universal-parameters/mode.md).
### B. Filter Your Requests
Use option chain filters to request only what you need:
**Option Chain Filters:**
- `strikeLimit`: Limit the number of strikes around the current price
- `expiration`: Filter to specific expiration dates
- `strike`: Filter to specific strike prices
- `type`: Filter to calls or puts only
**Example:**
```http
# Full chain: 20,000+ credits
GET https://api.marketdata.app/v1/options/chain/SPX/?expiration=all
# Filtered chain: ~100 credits (only at-the-money strikes)
GET https://api.marketdata.app/v1/options/chain/SPX/?expiration=all&strikeLimit=1
```
### C. Exclude Unnecessary Columns
Remove `bid`, `ask`, `mid`, and `last` columns when not needed. Responses without these columns = **1 credit regardless of symbol count**.
**How to exclude columns:**
- Use the `columns` parameter to specify only the data you need
- Critical for bulk endpoints: `stocks/quotes`, `stocks/prices`, `options/chain`
**Example:**
```http
# With quote columns: 100 credits (1 per symbol)
GET https://api.marketdata.app/v1/stocks/quotes/?symbols=AAPL,META,MSFT,...(100 symbols)
# Without quote columns: 1 credit (regardless of symbol count)
GET https://api.marketdata.app/v1/stocks/quotes/?symbols=AAPL,META,MSFT,...(100 symbols)&columns=symbol,volume,change
```
### D. Monitor Your Usage
**Check Headers After Each Request:**
- Always check `X-Api-Ratelimit-Consumed` after bulk requests
- Set up alerts when `X-Api-Ratelimit-Remaining` gets low
- Track which endpoints consume the most credits
**Example Monitoring Code:**
```python
from marketdata.client import MarketDataClient
def make_request_with_monitoring(client, method_call):
"""
Make an API request and monitor credit consumption.
Args:
client: MarketDataClient instance
method_call: Callable that makes the API request (e.g., lambda: client.stocks.quotes("AAPL"))
Returns:
The result of the API call
"""
result = method_call()
# Access rate limits after the request
rate_limits = client.rate_limits
consumed = rate_limits.requests_consumed
remaining = rate_limits.requests_remaining
limit = rate_limits.requests_limit
# Alert if credits are running low
if remaining < limit * 0.1: # Less than 10% remaining
print(f"WARNING: Only {remaining} credits remaining!")
# Log expensive requests (note: consumed shows total consumed, not per-request)
# You may need to track previous consumed value to calculate per-request consumption
return result
# Example usage
client = MarketDataClient()
quotes = make_request_with_monitoring(client, lambda: client.stocks.quotes("AAPL"))
```
```javascript
async function makeRequestWithMonitoring(url, headers) {
const response = await fetch(url, { headers });
const consumed = parseInt(response.headers.get('X-Api-Ratelimit-Consumed') || '0');
const remaining = parseInt(response.headers.get('X-Api-Ratelimit-Remaining') || '0');
const limit = parseInt(response.headers.get('X-Api-Ratelimit-Limit') || '0');
// Alert if credits are running low
if (remaining < limit * 0.1) { // Less than 10% remaining
console.log(`WARNING: Only ${remaining} credits remaining!`);
}
// Log expensive requests
if (consumed > 10) {
console.log(`Expensive request detected: ${consumed} credits consumed`);
}
return response;
}
```
### E. Avoid Redundant Requests
- **Cache responses** in your application
- Use `maxage` parameter with cached mode to control data freshness
- Implement request deduplication to avoid making the same request multiple times
## Understanding Your Plan Limits
Here are the credit limits for each plan:
| Plan | Daily Credits | Per Minute Credits |
|------|---------------|-------------------|
| Free Forever | 100 | No Limit |
| Starter | 10,000 | No Limit |
| Trader | 100,000 | No Limit |
| Quant | No Limit | 10,000 |
| Prime | No Limit | 100,000 |
### Reset Timing
- **Daily limits** reset at **9:30 AM Eastern Time** (NYSE opening bell)
- Use `America/New_York` timezone for accurate calculations
- **Quant and Prime plans** have per-minute limits (not daily limits)
- Check the `X-Api-Ratelimit-Reset` header for exact reset time
## When to Upgrade Your Plan
Consider upgrading if:
- **Free Forever → Starter**: Need more than 100 credits/day
- **Starter → Trader**: Need more than 10,000 credits/day or real-time data
- **Trader → Quant**: Need unlimited daily credits (10,000 credits/minute limit)
- **Trader → Prime**: Need unlimited daily credits with higher per-minute limit (100,000 credits/minute)
- **For bulk data users**: Quant/Prime plans are ideal for high-volume option chain or bulk stock requests
### Before Upgrading
1. **Calculate your actual credit needs** based on usage patterns
2. **Consider cached mode savings** - you may not need to upgrade if you optimize your requests
3. **Review your request patterns** - are you making unnecessary requests?
4. **Contact sales** for custom plans if standard plans don't fit your needs
## Common Scenarios: What Likely Happened to You
### Scenario 1: "I requested an option chain once and used all my credits"
**What happened:**
- You made a single request to `options/chain/SPX/` or similar
- The response contained thousands of option symbols
- Each symbol with quote data consumed 1 credit
**Why:**
- Full option chains contain thousands of symbols
- Each symbol with `bid`, `ask`, `mid`, or `last` data = 1 credit
**Solution:**
- Use filters (`strikeLimit`, `expiration`, etc.) to reduce the number of symbols
- Exclude quote columns if you don't need current prices
- Use cached mode: `?mode=cached` (1 credit per request)
**Prevention:**
- Always check `X-Api-Ratelimit-Consumed` after option chain requests
- Start with filtered requests to test credit consumption
- Use cached mode for bulk option chain retrieval
### Scenario 2: "I made 50 requests but used 500 credits"
**What happened:**
- You used bulk endpoints (`stocks/quotes`, `stocks/prices`, `options/chain`) with quote data
- Each request returned multiple symbols
- Each symbol in the response consumed 1 credit
**Why:**
- Bulk endpoints with quote data consume 1 credit per symbol
- 50 requests × 10 symbols each = 500 credits
**Solution:**
- Check `X-Api-Ratelimit-Consumed` header to see credit consumption per request
- Exclude unnecessary columns (`bid`, `ask`, `mid`, `last`) if not needed
- Use cached mode for bulk requests: `?mode=cached`
**Prevention:**
- Monitor headers after each bulk request
- Use cached mode for bulk data retrieval
- Exclude quote columns when current prices aren't needed
### Scenario 3: "My credits didn't reset at midnight"
**What happened:**
- You expected credits to reset at midnight
- Credits didn't reset when you expected
**Why:**
- Credits reset at **9:30 AM Eastern Time** (NYSE opening bell), not midnight
- This is consistent across all plans with daily limits
**Solution:**
- Wait until 9:30 AM ET
- Check `X-Api-Ratelimit-Reset` header for exact reset time
- Use `America/New_York` timezone for accurate calculations
**Prevention:**
- Understand reset timing for your plan
- Use the reset time header to calculate when credits will be available
- Plan your API usage around the 9:30 AM ET reset time
### Scenario 4: "I need to download entire option chains daily"
**What happened:**
- You need to retrieve full option chains regularly
- Each request consumes thousands of credits
- You quickly exhaust your daily limit
**Why:**
- Full option chains contain thousands of symbols
- Each symbol with quote data = 1 credit
- Daily limits are quickly exhausted with bulk requests
**Solution:**
- **Use cached mode**: `?mode=cached` (1 credit per request regardless of symbol count)
- **Upgrade to Quant/Prime plan**: Unlimited daily credits
- **Contact sales**: For custom plans if standard plans don't fit
**Prevention:**
- Always use cached mode for bulk data retrieval
- Consider upgrading if you regularly need large amounts of bulk data
- Filter requests to only get what you need
## Getting Help
If you've tried the strategies above and are still running out of credits, or if you need help understanding your usage patterns:
### When to Contact Support
- You've optimized your requests but still need more credits
- You're unsure which optimization strategy to use
- You need help calculating your credit needs
- You want to discuss custom plan options
### What to Include in Your Support Ticket
1. **Rate limit headers** from recent requests:
- `X-Api-Ratelimit-Consumed` values
- `X-Api-Ratelimit-Remaining` values
- `X-Api-Ratelimit-Limit` value
2. **Request examples** that consumed the most credits
3. **Your usage patterns**: What endpoints you use, how often, and for what purpose
4. **Your current plan** and whether you've tried cached mode
This information will help our support team understand your situation and provide the best guidance.