Put the credential and cache on the server
The widget should call a narrow same-origin endpoint such as your application’s fixtures route. That server route validates permitted competition, team, and date filters, adds the private bearer key, calls Stats API, and returns only the fields the widget needs. Never place a paid API credential in HTML, public JavaScript, or a client-visible environment variable.
Cache the normalized server response with a key built from stable IDs and filters. Include a generated-at or retrieved-at timestamp in the safe browser payload. This lets the widget show when it was updated without exposing internal headers. Choose the cache duration according to the fixture’s proximity and your product’s freshness promise.
Treat loading, empty, stale, and failed as different states
Render a clear loading state while the same-origin request is pending. A successful empty array should say that no fixtures match the selected range. A stale-but-allowed response should display its age. A transport or service error should preserve the last safe view where appropriate and explain that refresh failed, not that there are no matches.
Use semantic lists or tables, real time elements with machine-readable UTC values, and text labels that do not rely on color alone. Keep DOM updates small and escape text by assigning textContent rather than interpolating untrusted HTML. The result can stay fast and framework-free while meeting the same operational standards as a larger application.
const response = await fetch('/app-data/fixtures?team_id=team_example');
if (!response.ok) throw new Error('Fixtures unavailable');
const payload = await response.json();
renderFixtures(payload.data, payload.retrieved_at);
A handoff your agent can actually follow
Treat an AI agent as a planner and transformer, not as the database. Give it a narrow task, the exact resources it may call, the response fields it may quote, and a stop condition for missing data. Keep bearer credentials in the server-side tool implementation rather than in the prompt, transcript, browser, or generated source file.
The handoff below is deliberately operational. It asks for evidence before prose, makes uncertainty visible, and keeps the model inside the current football API contract. Adapt the output format to your product, but preserve the rules about stable IDs, UTC timestamps, freshness, and error handling.
Generate semantic HTML and dependency-free browser JavaScript.
Fetch from a same-origin server proxy, never directly with the private API key.
Render loading, empty, stale, success, and error states accessibly.
Cache normalized JSON on the server using the exact request filters.
What the human reviewer still owns
Automation can verify schemas and repeatable checks, but publication and product decisions still need a person. Review the selected competition, season, team, and match IDs; confirm that the time window matches the user’s question; and read the final answer against the retrieved JSON. A fluent explanation is not evidence that the underlying call was correct.
For time-sensitive football AI, record when the source was ingested and when the agent retrieved it. If the workflow cannot establish those timestamps, qualify the result instead of presenting it as current. The same rule applies to unavailable capabilities: do not quietly substitute fixtures or results for lineups, player statistics, odds, expected goals, injuries, or live events.
- Confirm every quoted fact appears in the retained API response.
- Exercise the empty, 401, 404, 429, and 503 paths before launch.
- Keep model interpretation separate from source facts in logs and user-facing output.
- Open the production browser bundle and network panel to confirm no private key or upstream Authorization header is present.
Continue with the contract, not a guess
Start with the public contract and coverage ledger, then move into implementation only when the capability you need is marked available. The related guide gives your next agent-first pattern without requiring an undocumented endpoint.