REST API
Read-only JSON for the report catalog, Snapshots, Pro analysis and track record.
A read-only JSON API over HTTPS with permissive CORS, so you can call it from a server, an agent or the browser. Every payload carries the standing research disclaimer. There are five endpoints in three access tiers: the catalog and track record are public, individual report content needs a free API key, and the full Pro analysis needs a key on a Pro account. The same data is also available to agents over MCP.
Access tiers at a glance
| Endpoint | Access | Returns |
|---|---|---|
| GET /api/v1/reports | Public | Catalog of editions |
| GET /api/v1/reports/{date}/{slug} | API key | One Snapshot + PDF link |
| GET /api/v1/reports/{date}/{slug}/pro | Key + Pro | Full Pro analysis + PDF |
| GET /api/v1/track-record | Public | Ledger stats + calibration |
| GET /api/v1/openapi.json | Public | OpenAPI 3.1 schema |
Authentication
Report-content endpoints are authenticated with a bearer API key. The key is an identity token tied to your account — it carries no tier itself. Send it on every gated request:
Authorization: Bearer af_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxGet your key
- Sign in at www.assetframe.co.uk (an account is required — the same one you use to read reports).
- Open the Account page → API access → Generate key.
- Copy the key — it’s shown once and stored only as a hash. You hold exactly one key at a time; Regenerate revokes the old one and issues a new one instantly.
How free vs Pro is decided
On each request the key is resolved to its owning account. Free-content endpoints accept any valid key. The /pro endpoint additionally checks that account for an active Pro subscription (admins included) — if it isn’t entitled you get 403. Because the check is per-request against the account, upgrading or cancelling takes effect immediately on the same key — there’s nothing to reissue.
# Full Pro analysis — key must belong to a Pro account
curl -H "Authorization: Bearer $ASSETFRAME_KEY" \
"https://www.assetframe.co.uk/api/v1/reports/2026-06-18/AAPL/pro"Base URL & schema
https://www.assetframe.co.uk/api/v1Machine-readable schema (OpenAPI 3.1), importable directly into agent platforms: https://www.assetframe.co.uk/api/v1/openapi.json
Rate limits
120 requests per minute — keyed per IP on the public endpoints and per API key on the authenticated ones. When you exceed it you get 429 too_many_requests with these headers:
Retry-After— seconds until you may retryRateLimit-Limit,RateLimit-Remaining,RateLimit-Reset(Unix epoch seconds)
Responses are also cached briefly at the edge. Need a higher limit for a documented use case? Get in touch.
Errors
// Every error shares the same shape:
{ "error": "<code>", "message": "<human-readable detail>" }
// 401 unauthorized Missing, malformed, revoked or unknown API key (gated endpoints).
// 403 forbidden Valid key, but the account has no active Pro subscription (/pro only).
// 404 not_found No published report for that date/slug.
// 429 too_many_requests Rate limit exceeded — see Retry-After + RateLimit-Reset headers.Endpoints
GET /api/v1/reports
Public — no key
List published editions as free Snapshot metadata. All query params are optional:
asset_class— short key (crypto,fx,equity,index,commodity,rates) or the exact display labelstatus— directional status (Buy,Sell,Wait)date— single ISO date (YYYY-MM-DD)q— free-text search over instrument name and tickerlimit— 1–200 (default 50)
curl "https://www.assetframe.co.uk/api/v1/reports?asset_class=crypto&limit=5"// GET /api/v1/reports?asset_class=crypto&limit=2
{
"total": 21,
"returned": 2,
"reports": [
{
"id": "2026-06-18/BTC",
"date": "2026-06-18",
"slug": "BTC",
"instrument": "Bitcoin",
"ticker": "BTC",
"assetClass": "Crypto - major",
"assetClassKey": "crypto",
"status": "Wait",
"risk": "High",
"bias": "Neutral",
"confidence": 55,
"windowEnd": "Fri 19 Jun 2026 22:00 UK",
"hasPro": true,
"url": "https://www.assetframe.co.uk/reports/2026-06-18/BTC"
}
],
"disclaimer": "AssetFrame publishes general market research ..."
}GET /api/v1/reports/{date}/{slug}
API key — any account
One report’s free Snapshot: full metadata, the Snapshot text, and a short-lived signed PDF link (~10 minutes). Path params: date (YYYY-MM-DD) and slug (e.g. BTC, AAPL). The Pro analysis lives at the /pro sub-resource below.
# Free Snapshot content — any valid key
curl -H "Authorization: Bearer $ASSETFRAME_KEY" \
"https://www.assetframe.co.uk/api/v1/reports/2026-06-18/AAPL"// GET /api/v1/reports/2026-06-18/AAPL
// Header: Authorization: Bearer af_live_...
{
"id": "2026-06-18/AAPL",
"date": "2026-06-18",
"slug": "AAPL",
"instrument": "Apple Inc.",
"ticker": "AAPL",
"assetClass": "US equity",
"assetClassKey": "equity",
"status": "Wait",
"risk": "High",
"bias": "Neutral",
"confidence": 55,
"windowEnd": "Thu 18 Jun 2026 21:00 UK",
"hasPro": true,
"url": "https://www.assetframe.co.uk/reports/2026-06-18/AAPL",
"snapshotText": "AssetFrame Snapshot — Apple Inc. (AAPL) ...",
"snapshotPdfUrl": "https://...r2.../free.pdf?X-Amz-Expires=600&...",
"proAvailable": true,
"proAccess": "Subscribe at https://www.assetframe.co.uk/pricing to unlock the full Pro analysis.",
"disclaimer": "AssetFrame publishes general market research ..."
}
// 401 → { "error": "unauthorized", "message": "Provide a valid API key: Authorization: Bearer af_live_..." }
// 404 → { "error": "not_found", "message": "No published report for that date/slug." }GET /api/v1/reports/{date}/{slug}/pro
API key + active Pro subscription
The full Pro analysis: metadata, the complete Pro text, and a short-lived signed Pro PDF link (~10 minutes). Returns 401 without a valid key and 403 if the key’s account isn’t a Pro subscriber.
# Full Pro analysis — key must belong to a Pro account
curl -H "Authorization: Bearer $ASSETFRAME_KEY" \
"https://www.assetframe.co.uk/api/v1/reports/2026-06-18/AAPL/pro"// GET /api/v1/reports/2026-06-18/AAPL/pro
// Header: Authorization: Bearer af_live_... (key must belong to a Pro account)
{
"id": "2026-06-18/AAPL",
"date": "2026-06-18",
"slug": "AAPL",
"instrument": "Apple Inc.",
"ticker": "AAPL",
"assetClass": "US equity",
"assetClassKey": "equity",
"status": "Wait",
"risk": "High",
"bias": "Neutral",
"confidence": 55,
"windowEnd": "Thu 18 Jun 2026 21:00 UK",
"hasPro": true,
"url": "https://www.assetframe.co.uk/reports/2026-06-18/AAPL",
"proText": "Apple Inc. (AAPL) — AssetFrame Pro ... (full multi-page analysis)",
"proPdfUrl": "https://...r2.../pro.pdf?X-Amz-Expires=600&...",
"disclaimer": "AssetFrame publishes general market research ..."
}
// 401 → { "error": "unauthorized", "message": "Provide a valid API key ..." }
// 403 → { "error": "forbidden", "message": "A Pro subscription is required. Subscribe at https://www.assetframe.co.uk/pricing." }GET /api/v1/track-record
Public — no key
The public, append-only track record: aggregate stats (reports scored, open calls, predictions graded, hit rate, streaks), the open (not-yet-graded) calls with their predictions, the scored results, and per-confidence calibration buckets.
curl "https://www.assetframe.co.uk/api/v1/track-record"// GET /api/v1/track-record
{
"stats": {
"reportsScored": 18,
"openCalls": 8,
"predictionsGraded": 54,
"hitRate": 61.1,
"longestStreak": 5,
"currentStreak": 2
},
"open": [ /* not-yet-graded calls, each with its predictions[] */ ],
"scored": [ /* append-only graded calls with per-prediction results */ ],
"calibration": {
"<=60": { "hitRate": 57.0, "n": 8 },
"61-75": { "hitRate": 64.0, "n": 7 },
">75": { "hitRate": 80.0, "n": 3 }
},
"disclaimer": "AssetFrame publishes general market research ..."
}GET /api/v1/openapi.json
Public — no key
The full OpenAPI 3.1 description of this API — paths, schemas, the ApiKeyAuth bearer scheme and error responses. Import it into ChatGPT Actions, LangChain or any OpenAPI client.
curl "https://www.assetframe.co.uk/api/v1/openapi.json"Use it from your agent
ChatGPT — Custom GPT Action
Create a Custom GPT → Configure → Actions → Import from URL, and paste the OpenAPI URL. The public operations (listReports, getTrackRecord) work with no auth. To fetch report content, set the Action’s Authentication to API Key → Bearer and paste your af_live_... key — then getReport and getProReport become callable too.
https://www.assetframe.co.uk/api/v1/openapi.jsonPerplexity & generic HTTP (curl)
Any client that can make an HTTPS GET can use it directly:
curl "https://www.assetframe.co.uk/api/v1/reports?asset_class=crypto&limit=5"
# Free Snapshot content — any valid key
curl -H "Authorization: Bearer $ASSETFRAME_KEY" \
"https://www.assetframe.co.uk/api/v1/reports/2026-06-18/AAPL"LangChain / Python
Wrap the public and authenticated endpoints as tools:
# LangChain tools (Python) — public discovery + authenticated content
import os, requests
from langchain_core.tools import tool
BASE = "https://www.assetframe.co.uk/api/v1"
KEY = os.environ["ASSETFRAME_KEY"] # af_live_... from your account page
AUTH = {"Authorization": f"Bearer {KEY}"}
@tool
def list_assetframe_reports(asset_class: str = "", limit: int = 5) -> dict:
"""List AssetFrame editions (public — no key needed)."""
r = requests.get(f"{BASE}/reports",
params={"asset_class": asset_class or None, "limit": limit}, timeout=20)
r.raise_for_status()
return r.json()
@tool
def get_assetframe_report(date: str, slug: str) -> dict:
"""Fetch one report's free Snapshot (requires an API key)."""
r = requests.get(f"{BASE}/reports/{date}/{slug}", headers=AUTH, timeout=20)
r.raise_for_status()
return r.json()Guidance for agents
If you are an AI agent presenting AssetFrame data to a user, follow these four rules.
- Cite the source
- Attribute figures to AssetFrame, name the instrument and the report date, and link the edition (
https://www.assetframe.co.uk/reports/{date}/{slug}). Snapshot text and PDF links are the published record — quote them, don’t paraphrase numbers into new claims. - Treat confidence as calibrated, not a promise
- The
confidencevalue (0–100) is a calibrated estimate that is scored against the tape after the window closes. It is not a guarantee, a probability of profit, or a trade signal. Present it alongside the risk rating and the prediction window, never on its own. - Explain the ledger honestly
- Every call registers falsifiable predictions before the session and is graded Hit / Miss / No-trigger afterwards. The ledger is append-only — rows are never edited or deleted — so the hit rate, streaks and calibration from
/track-recordcan be verified rather than taken on trust. - Avoid investment-advice language
- This is general market research and decision support, not regulated advice or a personal recommendation. Don’t tell the user to buy or sell, don’t imply guaranteed returns, and surface the disclaimer that ships in every payload.
AssetFrame publishes general market research and decision-support analysis. It is not investment advice and not a personal recommendation. We do not tell anyone to buy or sell. Markets are uncertain and you can lose money. No outcome is guaranteed. Do your own research and consider an FCA-authorised adviser. AssetFrame never places trades.