TutorialAI agentsAPI

Build a fund data app with Cursor or Claude Code in ten minutes

Use an AI coding agent to build a fund comparison page from ISINs. What an AGENTS.md for a financial data API must contain, and the prompts that work.Published 2 September 2026 · 7 min read · by FundFacts API

AI coding agents are good at gluing APIs together and bad at guessing what an API means. Give Cursor or Claude Code a fund data endpoint with no context and it will invent field names, hammer the quota, treat a two-minute cold request as a failure, and put the key in a React component. Give the same agent a well-written AGENTS.md and it builds the right thing on the first prompt. This post shows what that file must contain for a financial data API, then walks through building a fund comparison page with it. We use FundFacts API, whose Pro and Scale plans ship a ready-made AI companion kit, but the structure applies to any API you want agents to use well.

Why agents fail on data APIs

Three things go wrong repeatedly:

  1. Semantics. The agent sees "ter": "0.20%" and writes parseFloat(ter) / 100 in one place and Number(ter) in another. It does not know that empty strings mean "not disclosed", that weights are already in percent, or that profile.category is a stable classification while keyFacts.subAsset is display text.
  2. Operational rules. Rate limits, rolling windows, a first request that legitimately takes 15 seconds to 3 minutes, a 24-hour freshness cycle: none of this is visible from a JSON sample, so the agent sets a 10 s timeout, retries in a loop and burns the quota.
  3. Design choices. Asked for "a comparison page", the agent needs to know which fields belong in a comparison and which do not. Without guidance it shows the first ten keys it finds.

An AGENTS.md fixes all three by being the document the agent reads before writing code. Most agents pick it up automatically from the project root: Cursor, Claude Code, OpenAI Codex, GitHub Copilot's coding agent, Windsurf and Gemini CLI all look for it.

What a good AGENTS.md for a data API contains

The kit's AGENTS.md is about 500 lines, generated from the same field reference that renders the documentation. Its sections, in the order an agent should read them:

SectionWhat it settles
What the API is, and is notOne endpoint, ISIN in, factsheet out. No search, no bulk: iterate the user's ISINs.
Setup and the keyRead FUNDFACTS_API_KEY from the environment (or the embedded key), ask the user if missing, never ship it client-side.
Endpoint and envelopeEvery top-level key (cached, expiresAt, quota...) with its type and meaning.
Plan and rate limitsThe user's actual plan and window, the X-RateLimit-* headers, what counts as a request.
Freshness and latencyWarm vs cold ISINs, the 300 s timeout, "never fire the same request twice", cache locally until expiresAt.
ErrorsEach status and code with the one correct reaction (retry 502 twice, never retry 4xx, 404 means "not a fund").
Field referenceAll 74 fields of data as tables, with examples, grouped by identity, risk, portfolio, performance, metrics, freshness.
Rules for agentsNine numbered rules the agent must respect, from "show dataAsOf next to figures" to "do not scrape any site as a workaround".
Reference clientA 40-line TypeScript client with timeout, in-memory cache and typed errors, plus a Python equivalent.
RecipesComparison table, portfolio look-through, screener, factsheet page, change monitor, export: each with the exact fields to use and the pitfalls.

Two design points are worth copying whatever API you document. First, tell the agent what not to do: the rules section prevents most of the expensive mistakes (scraping, hard-coded keys, tight retry loops). Second, give it recipes, not just a schema: when a user asks for "a comparison page", the agent should recognise the recipe and follow it rather than design from scratch.

The kit adds three companions to AGENTS.md: a Cursor rule (.cursor/rules/fundfacts-api.mdc) and a Claude Code skill (.claude/skills/fundfacts-api/SKILL.md) that restate the hard rules in each tool's native format and point back to the long document, an OpenAPI 3.1 spec for client generators and MCP servers, and a fundfacts.d.ts with typed FundResponse and FundData.

Step 1: get the kit into the project

From the dashboard (Pro or Scale), choose a key mode and download fundfacts-agent-kit.zip:

  • Environment variable (default): the files reference FUNDFACTS_API_KEY. Safe to commit; the agent asks you for the key and writes it to .env.local.
  • Embedded key: a dedicated key named "AI companion kit" is created and written into the files. Zero setup, but keep those files out of shared repositories (a .gitignore.snippet is included) and revoke the key from the keys panel when you are done.

Unzip at the root of a fresh Next.js project:

bash
npx create-next-app@latest fund-compare --ts --app --no-tailwind --eslint --src-dir
cd fund-compare
unzip ~/Downloads/fundfacts-agent-kit.zip
echo "FUNDFACTS_API_KEY=ffk_..." >> .env.local # env mode only

Open the folder in Cursor or start claude in it. Both tools see AGENTS.md immediately; Cursor also loads the rule, Claude Code the skill.

Step 2: the first prompt

Be explicit about the recipe and the ISINs, and say where the key is. This prompt reliably produces a working page:

Read AGENTS.md. Build a server-rendered page at /compare that compares IE00B4L5Y983, IE00B3RBWM25 and LU1681043599 using the "fund comparison table" recipe: name, category, TER, risk indicator, 1-year and 3-year annualised returns, 3-year volatility, maximum drawdown and the top three sectors. Cache payloads on disk until expiresAt. Show a loading state that explains the first load can take a couple of minutes. The key is in FUNDFACTS_API_KEY.

What the agent does with the kit in place, and would not do without it:

  • Creates src/lib/fundfacts.ts from the reference client: 300 s timeout, bearer header, a typed FundFactsError, and a JSON-file cache keyed by ISIN with expiresAt.
  • Fetches the three ISINs sequentially (the recipe says "3 in parallel at most", and it knows a cold ISIN is slow).
  • Picks the fields the recipe lists: data.headlineMetrics.ter, data.riskRating, the 1 Year and 3 Years p.a. entries of data.annualisedReturns, data.headlineMetrics.volatility3y, data.metrics.maxDrawdown, the first three of data.sector.
  • Keeps formatted strings as published ("0.20%" stays "0.20%") and footnotes each row with data.dataAsOf, both from the rules section.
  • Handles 404 fund_not_found as "not a covered fund" with a visible message, and does not retry it.

The result is about 150 lines across three files, in three to five minutes including the first cold load.

Step 3: iterate with the recipes

Once the client exists, follow-up prompts are short because the agent already knows the vocabulary:

  • "Add a portfolio look-through: I hold 50/30/20 in these three. Aggregate sector and country exposure." The look-through recipe tells it to multiply each fund's weights by the portfolio weight and to caveat that top holdings are a lower bound.
  • "Turn each row into a factsheet page at /fund/[isin] with the growth chart." The factsheet recipe fixes the section order and says to plot indexedPerformance.points and only draw the index line when hasIndex is true.
  • "Add a nightly job that refreshes the payloads and e-mails me when a TER or risk rating changes." The change monitor recipe lists exactly which fields to diff.
  • "Export the comparison as CSV." The export recipe explains how to flatten dotted keys and serialise arrays.

Each of these is a one-line prompt because the design decisions are already written down.

Prompts that work, prompts that do not

Works: naming the recipe; listing ISINs explicitly; stating where the key is; asking for the loading state up front; asking the agent to "follow the rules in AGENTS.md section 8" when you review its code.

Does not work: "fetch all funds" (there is no list endpoint; give it ISINs); "make it real-time" (payloads refresh every 24 hours; the agent will say so if you ask, but it is better not to ask); "show everything" (74 fields is not a UI, pick a recipe).

If the agent ever proposes to scrape a fund website or a data vendor to fill a gap, that is the cue that it has not read the file: point it at rule 5 and it will stop.

Using the kit outside Cursor and Claude Code

  • OpenAI Codex and Copilot coding agent read AGENTS.md from the repository root; nothing else to do.
  • Windsurf, Gemini CLI, Aider and most others either read AGENTS.md or accept it as a context file.
  • ChatGPT / Claude in a browser: paste AGENTS.md into the conversation before asking for code. It is long, but it is the whole point.
  • Client generators and MCP servers: feed openapi.yaml to openapi-generator, Kiota, Stainless or an OpenAPI-to-MCP bridge to expose getFund as a tool a chat agent can call directly.

Regenerate when the API grows

The kit is built from the live field reference at download time, so when new fields appear in the documentation, download it again and replace the files. Because your project's code was written against named fields with the semantics spelled out, additions never break it; the agent simply has more to work with.

Ready to try it? Create a free account to explore the API, then upgrade to Pro to download the kit from your dashboard.

Try it on your own ISINs

One request returns key facts, holdings, risk and performance as JSON. Free plan, no card.