Every tool is a GET endpoint under https://api.fundalyze.ai/api/public/v1, with the tool's parameters as the query string and your API key as a bearer token.

Before you startLink to this section

  • An API key from Account → API & MCP, in an environment variable so it never lands in your code:

    export FUNDALYZE_API_KEY="fdz_live_YOUR_KEY"
    pip install requests

Your first callLink to this section

import os

import requests

response = requests.get(
    "https://api.fundalyze.ai/api/public/v1/get_financials",
    params={
        "ticker": "MSFT",
        "metrics": ["revenue", "operating_income", "net_income"],
        "years": 3,
    },
    headers={"Authorization": f"Bearer {os.environ['FUNDALYZE_API_KEY']}"},
    timeout=60,
)
response.raise_for_status()
answer = response.json()

print(answer["text"])  # the compact table an assistant would read
print(answer["link"])  # where to check the figures on fundalyze.ai
print("Calls left today:", response.headers.get("X-Quota-Remaining"))

A list parameter such as metrics can be sent as a Python list (requests repeats the parameter) or as one comma-separated string; the API accepts both.

Use data in codeLink to this section

text is laid out for a language model. In code, read data: the same content as JSON, with every field described on the tool's reference page.

data = answer["data"]
for metric in data["metrics"]:
    by_year = dict(zip(data["periods"], metric["values"]))
    print(metric["key"], by_year)
# revenue {'FY2024': 245122, 'FY2025': 281724, 'FY2026': 331839}  (USD millions)

A small clientLink to this section

Fundalyze runs one call at a time per key, so make calls one after another, not in parallel threads. This helper waits and retries when the key is still busy with an earlier call, stops when the day's quota is used, and raises the API's own message for anything else:

import os
import time

import requests

BASE = "https://api.fundalyze.ai/api/public/v1"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['FUNDALYZE_API_KEY']}"


class FundalyzeError(Exception):
    def __init__(self, status, detail):
        super().__init__(f"{status}: {detail}")
        self.status = status
        self.detail = detail


def call(tool, **params):
    for attempt in range(4):
        response = session.get(f"{BASE}/{tool}", params=params, timeout=60)
        if response.ok:
            return response.json()
        try:
            detail = response.json().get("detail", response.text)
        except ValueError:
            detail = response.text
        busy = response.status_code == 429 and "still running" in detail
        if busy and attempt < 3:
            time.sleep(1 + attempt)  # another call with this key is in flight
            continue
        raise FundalyzeError(response.status_code, detail)


apple = call("get_company", ticker="AAPL")
print(apple["data"]["name"], apple["data"]["sic_description"])

filings = call("list_filings", ticker="AAPL", form_type="10-K", limit=3)
for filing in filings["data"]["filings"]:
    print(filing["filing_date"], filing["form"], filing["sec_url"])

Errors come back as {"detail": "..."} with a status code; the message says what to fix (for example Unknown ticker: APPL. Use search_companies to find the symbol.). The full list is in Errors.

Without a keyLink to this section

Two endpoints need no key, which is handy for generating code or checking what exists:

import requests

tools = requests.get("https://api.fundalyze.ai/api/public/v1/tools", timeout=30).json()["tools"]
for tool in tools:
    print(tool["name"], "-", tool["description"].split(". ")[0])

dictionary = requests.get("https://api.fundalyze.ai/api/public/v1/dictionary", timeout=30).json()
print(len(dictionary["metrics"]), "metric keys")

Next: Limits and quotas, or a worked task in Recipes.

This page as Markdown, for language models and scripts: /developers/md/quickstart/python