{"record":{"id":"6a75b573059df08b","repo":"OpenBB-finance/OpenBB","slug":"congress-gov-api-rate-limit-exceeded-please-wait","errorCode":null,"errorMessage":"Congress.gov API rate limit exceeded. Please wait a moment and try again.","messagePattern":"Congress\\.gov API rate limit exceeded\\. Please wait a moment and try again\\.","errorType":"exception","errorClass":"OpenBBError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/congress_gov/openbb_congress_gov/utils/committees.py","lineNumber":191,"sourceCode":"        \"s\": \"is\",\n        \"sres\": \"is\",\n        \"sjres\": \"is\",\n        \"sconres\": \"is\",\n    }\n\n    kwargs: dict = {}\n\n    if session is not None:\n        kwargs[\"session\"] = session\n\n    bills_base = f\"{base_url}committee/{chamber}/{system_code}/bills\"\n    first_url = f\"{bills_base}?format=json&limit=250&offset=0&api_key={api_key}\"\n    resp = await amake_request(first_url, timeout=20, **kwargs)\n    all_bills: list[dict] = []\n\n    if isinstance(resp, dict):\n        if resp.get(\"error\", {}).get(\"code\") == \"OVER_RATE_LIMIT\":\n            raise OpenBBError(\n                ValueError(\n                    \"Congress.gov API rate limit exceeded. Please wait a moment and try again.\"\n                )\n            )\n\n        cb = resp.get(\"committee-bills\", {})\n        all_bills = list(cb.get(\"bills\", []) if isinstance(cb, dict) else [])\n        total = resp.get(\"pagination\", {}).get(\"count\", 0)\n\n        if total > 250 and all_bills:\n            remaining_urls = [\n                f\"{bills_base}?format=json&limit=250&offset={off}&api_key={api_key}\"\n                for off in range(250, total, 250)\n            ]\n            page_sem = asyncio.Semaphore(10)\n\n            async def _fetch_bills_page(page_url: str) -> list[dict]:\n                async with page_sem:","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/congress_gov/openbb_congress_gov/utils/committees.py#L173-L209","documentation":"Raised as OpenBBError from fetch_committee_bills when the Congress.gov API responds with error code OVER_RATE_LIMIT. Congress.gov enforces a request quota (5,000 requests/hour per API key as of writing); once exceeded, every response carries that error code instead of data. The helper checks the error envelope on the first page response and aborts the pagination immediately.","triggerScenarios":"Fetching all bills for a committee whose pagination.count exceeds 250, generating many back-to-back page requests; running multiple concurrent workers or dashboards against the same congress_gov_api_key; tight refetch intervals on Workspace widgets.","commonSituations":"Shared API key across a team or CI; batch/backfill scripts looping over many committees; a scheduled job overlapping the hourly window reset.","solutions":["Wait for the rate-limit window to reset (typically the top of the next hour) and retry","Reduce request volume: use use_cache=True, lower refetch frequency, or batch fewer committees per run","Provision a separate Congress.gov API key (free at api.congress.gov) for heavy consumers so keys are not shared"],"exampleFix":"# before\nfor code in ['hsju00', 'ssju00', 'hsba00']:\n    bills = await fetch_committee_bills(chamber, code, api_key)\n\n# after\nfor code in ['hsju00', 'ssju00', 'hsba00']:\n    try:\n        bills = await fetch_committee_bills(chamber, code, api_key)\n    except OpenBBError as e:\n        if 'OVER_RATE_LIMIT' in str(e) or 'rate limit' in str(e).lower():\n            await asyncio.sleep(3600)  # wait out the window\n        raise","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"from openbb_core.app.model.abstract.error import OpenBBError\n\nasync def fetch_with_backoff(fetch, *a, max_retries=5, **kw):\n    for attempt in range(max_retries):\n        try:\n            return await fetch(*a, **kw)\n        except OpenBBError as e:\n            if 'rate limit' not in str(e).lower() or attempt == max_retries - 1:\n                raise\n            await asyncio.sleep(min(60 * (2 ** attempt), 900))","preventionTips":["Enable use_cache=True for committee document/bill fetches","Stagger batch jobs to stay well under the 5,000 req/hour key quota","Use a dedicated API key per team/system to isolate quotas"],"tags":["congress-gov","rate-limit","network","retry"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}