> For the complete documentation index, see [llms.txt](https://www.bluegamma.io/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.bluegamma.io/documentation/integrations/api/rate-limits.md).

# Rate Limits & Best Practices

Rate limits and best practices for using the BlueGamma API efficiently.

This guide covers rate limits, caching strategies, and best practices for integrating with the BlueGamma API.

***

### Rate Limits

BlueGamma applies rate limits to ensure fair usage and service reliability. The limits below apply to paid API plans.

| Limit               | Value                           |
| ------------------- | ------------------------------- |
| Requests per second | 20                              |
| Burst allowance     | 50 requests                     |
| Monthly volume      | 1,000,000 requests (soft limit) |

The burst allowance lets you make up to 50 requests in a short burst before rate limiting kicks in. After that, requests are throttled to 20 per second.

If you exceed the per-second limits, you'll receive a `429 Too Many Requests` response with a `Retry-After` header: wait that many seconds before retrying. The monthly figure is a soft limit: sustained usage beyond it prompts a conversation about your plan rather than hard blocking.

Keys you create in the app on a trial or a self-serve subscription have lower limits: 5 requests per second, bursts of up to 20, and a daily quota.

Limits are set per API key. Every response carries your key's limits in the `RateLimit-Policy` header, and a request over any of them returns `429`.

{% hint style="info" %}
**Need higher limits?** Contact us at <support@bluegamma.io> to discuss your requirements.
{% endhint %}

***

### Best Practices

#### 1. Cache Responses

Curve data doesn't change every second. Cache responses to reduce API calls:

```python
import requests
from functools import lru_cache
from datetime import datetime

API_KEY = "your_api_key"

@lru_cache(maxsize=100)
def _fetch_swap_rate(index: str, maturity: str, cache_minute: str):
    response = requests.get(
        "https://api.bluegamma.io/v1/swap_rate",
        params={
            "index": index,
            "start_date": "0D",
            "maturity_date": maturity,
            "fixed_leg_frequency": "6M",
        },
        headers={"x-api-key": API_KEY}
    )
    return response.json()

def get_swap_rate(index: str, maturity: str):
    # The cache key changes every minute, so a cached rate is at most a minute old
    return _fetch_swap_rate(index, maturity, datetime.now().strftime("%Y-%m-%d %H:%M"))
```

**Recommended cache durations:**

| Data Type                 | Cache Duration           |
| ------------------------- | ------------------------ |
| Swap rates                | 1-5 minutes              |
| Forward curves            | 1-5 minutes              |
| Historical data           | 24 hours or longer       |
| Government yields (US)    | 1-5 minutes              |
| Government yields (other) | 24 hours (updated daily) |

#### 2. Batch Your Requests

Instead of making separate calls for each tenor, use curve endpoints that return multiple data points:

**❌ Inefficient — 8 separate calls:**

```python
maturities = ["1Y", "2Y", "3Y", "5Y", "7Y", "10Y", "20Y", "30Y"]
for maturity in maturities:
    get_swap_rate("SOFR", maturity)  # 8 API calls
```

**✅ Efficient — 1 call:**

```python
get_swap_curve("SOFR")  # Returns all tenors in one call
```

**✅ Efficient: many individual swap rates in 1 call**

When you need swap rates a curve endpoint doesn't cover, such as different indices, start dates or conventions, send them together to `POST /v1/swap_rate/batch`, up to 50 per request:

```python
response = requests.post(
    "https://api.bluegamma.io/v1/swap_rate/batch",
    json={"items": [
        {"index": "SOFR", "start_date": "SPOT", "maturity_date": "5Y"},
        {"index": "6M EURIBOR", "start_date": "SPOT", "maturity_date": "10Y"},
    ]},
    headers={"x-api-key": API_KEY}
)
```

Each item takes the same parameters as `/swap_rate`, and results come back in the order you sent them. See [Fetching a Swap Rate](/documentation/integrations/api/how-to-guides/fetching-a-swap-rate.md) for the full response.

#### 3. Use Appropriate Endpoints

| If you need...            | Use this endpoint                         |
| ------------------------- | ----------------------------------------- |
| Single swap rate          | `/swap_rate`                              |
| Several single swap rates | `/swap_rate/batch` (POST, up to 50 items) |
| Full swap curve           | `/get_swap_curve`                         |
| Single forward rate       | `/forward_rate`                           |
| Full forward curve        | `/forward_curve`                          |
| Single discount factor    | `/discount_factor`                        |
| Full discount curve       | `/discount_curve`                         |

#### 4. Handle Errors Gracefully

Implement retry logic with backoff. On a `429`, wait the number of seconds in the `Retry-After` header before retrying:

```python
import time
import requests

def api_request_with_retry(url, params, max_retries=3):
    headers = {"x-api-key": API_KEY}
    
    for attempt in range(max_retries):
        response = requests.get(url, params=params, headers=headers)
        
        if response.status_code == 200:
            return response.json()
        
        if response.status_code == 429:
            # Rate limited: wait the Retry-After seconds, then retry
            wait_time = int(response.headers.get("Retry-After", 2 ** attempt))
            print(f"Rate limited. Waiting {wait_time}s...")
            time.sleep(wait_time)
            continue
        
        if response.status_code >= 500:
            # Server error — retry
            time.sleep(1)
            continue
        
        # Client error — don't retry
        response.raise_for_status()
    
    raise Exception("Max retries exceeded")
```

#### 5. Use Valuation Time for Consistency

{% hint style="warning" %}
Keys created on the **API Keys** page (trial and self-serve keys) cover live data only. They reject `valuation_time` and `valuation_date`, and cannot call `/historical_swap_rates`, `/bond_price` or `/bond_yield`. Omit `valuation_time` and every endpoint values as of now. To use the pattern below, historical access has to be enabled on your key: email <sales@bluegamma.io>.
{% endhint %}

When building a model that requires multiple data points, use the same `valuation_time` parameter across all requests to ensure consistency:

```python
valuation_time = "2024-12-15T16:00:00"

swap_rate = requests.get(
    "https://api.bluegamma.io/v1/swap_rate",
    params={"index": "SOFR", "start_date": "SPOT", "maturity_date": "5Y",
            "fixed_leg_frequency": "6M", "valuation_time": valuation_time},
    headers=headers
)
discount_factor = requests.get(
    "https://api.bluegamma.io/v1/discount_factor",
    params={"index": "SOFR", "date": "2030-12-31", "valuation_time": valuation_time},
    headers=headers
)
gov_yield = requests.get(
    "https://api.bluegamma.io/v1/gov_yield",
    params={"country_code": "US", "maturity": "5Y", "valuation_time": valuation_time},
    headers=headers
)
```

This ensures all data points are from the same market snapshot. Use `start_date="SPOT"` with `valuation_time`: a tenor such as `0D` counts from today, not from the valuation time.

***

### Common Mistakes to Avoid

| Mistake                                    | Solution                                       |
| ------------------------------------------ | ---------------------------------------------- |
| Calling API in a tight loop                | Batch requests or add delays                   |
| Not caching historical data                | Cache historical queries — they won't change   |
| Fetching full curves when you need 1 point | Use single-point endpoints for one-off queries |
| Not handling 429 responses                 | Wait the `Retry-After` seconds, then retry     |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://www.bluegamma.io/documentation/integrations/api/rate-limits.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
