{"record":{"id":"efa633e108fdb25f","repo":"OpenBB-finance/OpenBB","slug":"unauthorized-fmp-request-error-message","errorCode":null,"errorMessage":"Unauthorized FMP request -> {error_message}","messagePattern":"Unauthorized FMP request -> (.+?)","errorType":"http","errorClass":"UnauthorizedError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/fmp/openbb_fmp/utils/helpers.py","lineNumber":36,"sourceCode":"\n    data = await response.json()\n\n    if isinstance(data, dict):\n        error_message = data.get(\"Error Message\", data.get(\"error\"))\n\n        if error_message is not None:\n            conditions = (\n                \"upgrade\" in error_message.lower()\n                or \"exclusive endpoint\" in error_message.lower()\n                or \"special endpoint\" in error_message.lower()\n                or \"premium query parameter\" in error_message.lower()\n                or \"subscription\" in error_message.lower()\n                or \"unauthorized\" in error_message.lower()\n                or \"premium\" in error_message.lower()\n            )\n\n            if conditions:\n                raise UnauthorizedError(f\"Unauthorized FMP request -> {error_message}\")\n\n            raise OpenBBError(\n                f\"FMP Error Message -> Status code: {response.status} -> {error_message}\"\n            )\n\n    return data\n\n\nasync def get_data(url: str, **kwargs: Any) -> list | dict:\n    \"\"\"Get data from FMP endpoint.\"\"\"\n    # pylint: disable=import-outside-toplevel\n    from openbb_core.provider.utils.helpers import amake_request\n\n    return await amake_request(url, response_callback=response_callback, **kwargs)\n\n\nasync def get_data_urls(urls: list[str], **kwargs: Any) -> list | dict:\n    \"\"\"Get data from FMP for several urls.\"\"\"","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/fmp/openbb_fmp/utils/helpers.py#L18-L54","documentation":"Raised in FMP's response_callback when the HTTP body is a JSON dict containing an 'Error Message'/'error' field whose text matches authorization keywords: upgrade, exclusive endpoint, special endpoint, premium query parameter, subscription, unauthorized, or premium. It signals the FMP plan does not cover the requested endpoint or parameter, as opposed to a bad key (which usually yields a non-200 handled by error 445).","triggerScenarios":"Free or Starter FMP key calling endpoints like analyst estimates, insider trading, or passing premium-only query parameters; FMP returns HTTP 200 with {'Error Message': '...Upgrade your subscription...'} which the keyword scan then matches.","commonSituations":"Following code examples that use premium endpoints while holding a free key; FMP moving an endpoint from free to paid in a plan change; using a query parameter (e.g. short=true) reserved for higher tiers.","solutions":["Match the endpoint against FMP's current pricing page to see which tier includes it","Upgrade the FMP subscription, or switch the OpenBB call to a provider whose coverage includes the data on your existing plan","Remove premium-only query parameters from the call","Confirm you are not accidentally using a different key than the one with the correct tier (multiple keys in env/credentials)"],"exampleFix":"# before\nres = await obb.equity.estimates.analyst_estimates(symbol='AAPL', provider='fmp').await_to_list()  # premium\n\n# after - use a provider that covers it on your plan\nres = await obb.equity.estimates.analyst_estimates(symbol='AAPL', provider='benzinga').await_to_list()","handlingStrategy":"try-catch","validationCode":"# FMP exposes plan limits in the profile response headers/body of a probe call\nr = requests.get(f\"https://financialmodelingprep.com/api/v3/profile/AAPL?apikey={key}\")\nbody = r.json()\nif isinstance(body, dict) and ('Error Message' in body or 'error' in body):\n    raise RuntimeError(f'FMP plan issue: {body}')","typeGuard":null,"tryCatchPattern":"from openbb_core.provider.utils.errors import UnauthorizedError\ntry:\n    data = await fetcher.fetch_data(query, credentials)\nexcept UnauthorizedError:\n    data = await fallback_fetcher.fetch_data(query, other_credentials)  # different provider/plan","preventionTips":["Match requested endpoints against the FMP plan's feature matrix before shipping","Keep a fallback provider configured for premium-only datasets","Run integration smoke tests that hit the exact endpoints your app uses"],"tags":["fmp","subscription","premium","authorization"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}