Rate Limits & Quotas¶
The Tessellate Renewables API enforces rate limits and monthly quotas to ensure fair usage and service stability.
Subscription Tiers¶
| Tier | Monthly Requests | Rate Limit | Price |
|---|---|---|---|
| Free | 100 | 10/min | $0 |
| Starter | 5,000 | 60/min | $99 (one-time) |
| Pro | 50,000 | 300/min | $499/year |
| Enterprise | Unlimited | 1000/min | $1,499/year |
Rate Limits¶
Rate limits are enforced per API key using a sliding window algorithm.
How It Works¶
- Window: 60 seconds (sliding)
- Limit: Based on your tier
- Scope: Per API key
Response Headers¶
Every API response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests per minute |
X-RateLimit-Remaining |
Requests remaining in current window |
X-RateLimit-Reset |
Seconds until window resets |
Rate Limit Exceeded (429)¶
When you exceed the rate limit:
{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded. Maximum 60 requests per minute.",
"retry_after": 12,
"limit": 60,
"window_seconds": 60
}
Best Practice: Implement exponential backoff:
import time
import requests
def make_request_with_retry(url, headers, data, max_retries=3):
for attempt in range(max_retries):
response = requests.post(url, headers=headers, json=data)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 5))
time.sleep(retry_after)
continue
return response
raise Exception("Max retries exceeded")
Monthly Quotas¶
Monthly quotas reset on the 1st of each month at 00:00 UTC.
Response Headers¶
| Header | Description |
|---|---|
X-Quota-Limit |
Monthly request limit |
X-Quota-Used |
Requests used this month |
X-Quota-Remaining |
Requests remaining this month |
Quota Exceeded (402)¶
When you exceed your monthly quota:
{
"error": "quota_exceeded",
"message": "Monthly quota exceeded. 5000/5000 requests used.",
"current_usage": 5000,
"limit": 5000,
"tier": "STARTER",
"upgrade_url": "/billing/pricing"
}
Note: Status code 402 (Payment Required) indicates you need to upgrade.
Checking Usage¶
Via API¶
Response:
{
"rate_limit": {
"requests_in_window": 5,
"window_seconds": 60,
"limit_per_minute": 60,
"remaining": 55,
"tier": "STARTER"
},
"quota": {
"requests_this_month": 127,
"monthly_limit": 5000,
"remaining": 4873,
"percent_used": 2.54,
"tier": "STARTER",
"period_start": "2026-01-01T00:00:00Z",
"period_end": "2026-02-01T00:00:00Z"
},
"summary": {
"total_requests": 127,
"successful_requests": 125,
"failed_requests": 2,
"avg_response_time_ms": 1250.5,
"success_rate": 0.984
}
}
Via Dashboard¶
- Log in to tessellaterenewables.com
- Navigate to Settings → API Usage
- View real-time usage metrics and history
Metered Endpoints¶
The following endpoints count against your quota:
| Endpoint | Description |
|---|---|
POST /solar/optimization/quick |
Quick optimization |
POST /solar/optimization/run |
Full optimization job |
POST /solar/optimization/multi |
Multi-objective optimization |
GET /solar/optimization/{job_id} |
Get job results |
POST /solar/resource |
Solar resource data |
POST /solar/predict |
Energy prediction |
POST /solar/assess |
Site assessment |
POST /solar/report |
Generate report |
Non-Metered Endpoints¶
These endpoints do not count against your quota:
GET /solar/health- Health checkGET /metering/*- Usage endpointsGET /billing/*- Billing endpointsGET /auth/*- Authentication endpoints
Handling Limits in Code¶
Python Example¶
import os
import time
import requests
class TessellateClient:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = "https://api.tessellaterenewables.com"
def _request(self, method, path, **kwargs):
url = f"{self.base_url}{path}"
headers = kwargs.pop('headers', {})
headers['X-API-Key'] = self.api_key
response = requests.request(method, url, headers=headers, **kwargs)
# Log rate limit info
limit = response.headers.get('X-RateLimit-Limit')
remaining = response.headers.get('X-RateLimit-Remaining')
if limit:
print(f"Rate limit: {remaining}/{limit}")
# Handle rate limiting
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 5))
print(f"Rate limited. Waiting {retry_after}s...")
time.sleep(retry_after)
return self._request(method, path, **kwargs)
# Handle quota exceeded
if response.status_code == 402:
raise Exception("Monthly quota exceeded. Please upgrade your plan.")
response.raise_for_status()
return response.json()
def optimize(self, site, objective='energy'):
return self._request('POST', '/solar/optimization/quick', json={
'site': site,
'objective': objective
})
JavaScript Example¶
class TessellateClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.tessellaterenewables.com';
}
async request(method, path, body = null) {
const response = await fetch(`${this.baseUrl}${path}`, {
method,
headers: {
'Content-Type': 'application/json',
'X-API-Key': this.apiKey
},
body: body ? JSON.stringify(body) : null
});
// Handle rate limiting
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '5');
await new Promise(r => setTimeout(r, retryAfter * 1000));
return this.request(method, path, body);
}
// Handle quota exceeded
if (response.status === 402) {
throw new Error('Monthly quota exceeded. Please upgrade your plan.');
}
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return response.json();
}
}
Upgrading Your Plan¶
When you approach or exceed your limits:
- Go to Settings → Billing in the dashboard
- Click Upgrade Plan
- Select a higher tier
- Complete payment via Stripe
Or upgrade via API:
curl -X POST https://api.tessellaterenewables.com/billing/create-checkout-session \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"tier": "PRO"}'
Tips for Staying Within Limits¶
- Cache results - Don't re-fetch data that hasn't changed
- Batch operations - Use multi-objective optimization instead of multiple single runs
- Poll efficiently - Use reasonable intervals when checking job status
- Monitor usage - Set up alerts before hitting limits
Enterprise Options¶
For high-volume usage, contact us for:
- Custom rate limits
- Dedicated infrastructure
- SLA guarantees
- Volume discounts
Email: [email protected]