Errors & Rate Limits

Standard error envelope, SDK exception mapping, and per tier rate limits.

Errors

All errors return a JSON envelope with code, message, and status. The SDK maps each code to a typed exception inheriting from MarketlensError. The 429 and 402 errors additionally carry structured fields inside the error object: limit, reset (Unix seconds, absent on the free allowance, which does not reset), upgrade_url, used (budget walls), rows_needed (an export that does not fit the free allowance), and topup_url (the monthly row wall). HISTORY_WINDOW_EXCEEDED carries window_start (where the free window begins), data_end (when the market ended), both in epoch milliseconds, and upgrade_url.

Error codes
MARKET_NOT_FOUNDNotFoundError (404)
Market does not exist.
EVENT_NOT_FOUNDNotFoundError (404)
Event does not exist.
SERIES_NOT_FOUNDNotFoundError (404)
Series does not exist.
KEY_NOT_FOUNDNotFoundError (404)
API key not found.
DATA_NOT_AVAILABLEDataNotAvailableError (404)
No order book data for the market or time. Carries requested_at and coverage.
INVALID_PARAMETERInvalidParameterError (400)
Invalid or missing query parameter.
RANGE_TOO_LARGEInvalidParameterError (400)
Time range exceeds the allowed maximum for this endpoint.
CURSOR_EXPIREDInvalidParameterError (400)
Pagination cursor older than 24 hours.
UNAUTHORIZEDAuthenticationError (401)
Missing or invalid API key.
FORBIDDENForbiddenError (403)
Insufficient permissions.
TIER_LIMIT_REACHEDForbiddenError (403)
Feature not available on current tier.
HISTORY_WINDOW_EXCEEDEDHistoryWindowError (403)
The market's data ended before the free 7 day window. Not auto-retried. Carries window_start, data_end, and upgrade_url.
FREE_ALLOWANCE_EXHAUSTEDFreeAllowanceExhaustedError (402)
Free data row allowance used up. Not auto-retried. Carries used, limit, upgrade_url, and rows_needed on exports.
RATE_LIMITEDRateLimitError (429)
RPM burst limit exceeded. Auto-retried by the SDK. Carries limit, reset, and upgrade_url.
DAILY_BUDGET_EXCEEDEDDailyBudgetExceededError (429)
Legacy daily budget, only on grandfathered paid seats. Not auto-retried by the SDK. Carries used, limit, reset, and upgrade_url.
ROW_LIMIT_EXCEEDEDRowLimitExceededError (429)
Monthly data row allowance exhausted (paid tiers). Not auto-retried. Carries used, limit, reset, upgrade_url, and topup_url.
UNIT_LIMIT_EXCEEDEDRequestUnitsExceededError (429)
Daily request unit budget exhausted. Not auto-retried. Carries used, limit, reset, and upgrade_url.
STORE_UNAVAILABLEStoreUnavailableError (503)
The history file store did not respond in time. Auto-retried by the SDK after Retry-After, backtests skip the market, and the request's units are refunded.

Non HTTP exceptions: ConnectionError on network failure, TimeoutError after 30s (configurable). The SDK retries 429 and 5xx errors with exponential backoff (default 2 retries, configurable via max_retries). DAILY_BUDGET_EXCEEDED, ROW_LIMIT_EXCEEDED, and UNIT_LIMIT_EXCEEDED are not retried since those budgets reset at fixed times (midnight UTC, or the first of the month for the monthly row allowance).

jsonResponse
{ "error": { "code": "MARKET_NOT_FOUND", "message": "Market abc... not found", "status": 404 } }
jsonResponse
{ "error": { "used": 2000123, "limit": 2000000, "upgrade_url": "https://marketlens.trade/console/billing?checkout=pro", "code": "FREE_ALLOWANCE_EXHAUSTED", "message": "Free data allowance used up (2,000,123 of 2,000,000 rows). Free rows do not reset.\nUpgrade to Pro for the full archive and 5,000,000,000 rows a month ($39/mo): https://marketlens.trade/console/billing?checkout=pro", "status": 402 } }
python
from marketlens import MarketLens, NotFoundError, RateLimitError try: book = client.orderbook.get("nonexistent-id") except NotFoundError as e: print(e.code, e.message) except RateLimitError as e: print(f"Retry after {e.retry_after}s")

Rate Limits

Triple gated: a per-minute burst limit (RPM), a daily request-unit budget (1 unit per request, 5 for order book history), and a data row allowance, all tracked per user across all API keys. Query endpoints bill rows returned; exports bill a file's rows once ever, so re-downloads and series polling are free. Free gets 2M rows and markets open in the last 7 days; Pro and Scale get a monthly allowance and the full archive since March 2026. Catalog endpoints (markets, events, series, and signal surfaces) bill neither rows nor units, so browsing the catalog costs nothing against either allowance and keeps working after both are exhausted. Only RPM applies to them.

TierRPMData rowsUnits/dayKeysPrice
Free1802M once25K1$0
Pro3,6005B/month2M5$348/yr or $39/mo
Scale10,80050B/month8M25$1,788/yr or $199/mo
Response headers
X-RateLimit-Limit
RPM limit for this user.
X-RateLimit-Remaining
Requests remaining in current 60s window.
X-RateLimit-Reset
Unix timestamp when window resets.
X-Rows-Limit
Data row allowance: the one time allowance on Free, the calendar month allowance on paid tiers.
X-Rows-Remaining
Rows remaining, including rollover.
X-Rows-Reset
Unix timestamp when the row allowance resets. Absent on Free, where nothing resets.
X-Units-Limit
Request unit budget per UTC day. Most requests cost 1 unit, order book history costs 5, and catalog endpoints cost nothing.
X-Units-Remaining
Units remaining today.
X-Units-Reset
Unix timestamp of next UTC midnight.
X-EventBudget-*
Deprecated aliases of the X-Rows-* trio, kept for one SDK minor version.
X-Export-Rows
Rows charged by an export response. Zero when the file was already unlocked by this account.
X-Export-Events
Deprecated: the export file's full row count, kept for one SDK minor version.
Retry-After
Seconds to wait (included on 429).