Harcourt Valuations produces institutional-grade Net Asset Value (NAV) reports for mining companies. Each report contains a full discounted cash flow (DCF) model for every mine or project owned by the company, a P/NAV ratio, and a two-way sensitivity table showing how NAV per share moves with metal prices and discount rates.
The core thesis: the answer is a number. Mining equity analysis should produce a specific, defensible per-share value — not a narrative. P/NAV (price to net asset value) is the primary metric used by mining-focused fund managers and sell-side analysts at major Canadian and Australian banks.
harcourt_nav_query_api).POST https://reports.harcourtvaluations.ai/chat. Powered by Claude Haiku.
Returns current P/NAV, NAV/share, and key catalyst for any covered ticker. Does not require
payment.GET https://reports.harcourtvaluations.ai/catalog
returns all covered companies in JSON with metadata.This page does not list them. Coverage changes as models are completed, and any list written here would be a copy that drifts from the source. Two live endpoints answer it, both free, both requiring no authentication:
| Endpoint | Answers |
|---|---|
GET https://reports.harcourtvaluations.ai/catalog |
Every covered company: name, ticker string with all listings, primary commodity, key assets, NAV, P/NAV, model date, and the free teaser. This is the authoritative coverage list. |
GET https://reports.harcourtvaluations.ai/nav-debug |
Which of those companies has a sensitivity matrix, and that matrix's real
extent — has_sensitivity, matrix_rows (the commodity
axis points) and matrix_cols (the discount rates). Keyed by the
same ticker stem /nav-query/{ticker} takes. Read from the model's
own exported grid, so it cannot disagree with what /nav-query
will do. |
Resolving a company to its API ticker. Use the key from
/nav-debug directly — it is the path segment /nav-query expects.
Do not derive it from the ticker string in /catalog: for Seabridge Gold that
string is TSX: SEA · NYSE: SA and the API ticker is sa, not
sea. The listing symbol and the API ticker are not the same identifier.
Determining a company's commodity parameter. Call
/nav-query/{ticker}?rate=0.08 with no commodity parameter. The response echoes
the axis under inputs and names it in defaulted_inputs, so one
call tells you what the axis is. Sending the wrong parameter is also safe and
self-correcting: it returns 400 naming the parameter that ticker actually
takes, rather than interpolating your value against an unrelated axis.
The NAV Query API returns a modelled NAV per share at caller-specified inputs. It does not re-run any live model. Instead, it reads a precomputed sensitivity matrix stored in Cloudflare R2 and performs bilinear interpolation between the nearest grid points. Response time is typically under 50ms.
https://reports.harcourtvaluations.ai/nav-query/{ticker}?{commodity}={value}&rate={discount_rate}
No authentication required. Rate limits may apply at high volume. For production agent workflows, use the Qatom MCP tool below.
The commodity parameter name is not currently validated against the ticker's grid
axis. Sending ?gold= to a silver-axis ticker will interpolate the value
against the silver axis and return a plausible-looking number rather than an error. Always read
the echoed inputs object in the response, which names the axis actually used, and
send the parameter listed for that ticker in the coverage table above.
| Parameter | Type | Description | Applies To |
|---|---|---|---|
gold | number | Gold price, USD per troy oz (e.g. 4000) | Tickers whose grid carries a gold axis |
silver / ag | number | Silver price, USD per troy oz (e.g. 61) | Tickers whose grid carries a silver axis |
cu / copper | number | Copper price, USD per lb (e.g. 6.5) | Tickers whose grid carries a copper axis |
zn / zinc | number | Zinc price, USD per lb (e.g. 1.62) | Tickers whose grid carries a zinc axis |
pb / lead | number | Lead price, USD per lb | Tickers whose grid carries a lead axis |
u3o8 | number | Uranium price, USD per lb U3O8 (e.g. 82) | Tickers whose grid carries a uranium axis |
row | number | Generic axis value, accepted on any ticker with exactly one commodity axis. On a multi-axis ticker it names nothing and is refused with 400, listing the parameters to send instead — so it is a fallback, not a universal escape hatch. | Single-axis tickers |
rate | number | Discount rate as a decimal (e.g. 0.08 = 8%). Omit it and the grid's own base rate is used and reported in defaulted_inputs. | All |
{
"ticker": "{ticker}",
"model_date": "YYYY-MM-DD",
"model_version": "{model version}",
"inputs": { "{axis_key}": 0.0, "discount_rate": 0.08 },
"defaulted_inputs": null, // axis keys filled from the model's own deck
// because the caller did not name them
"axes": [ // multi-axis grids only
{ "axis": "{axis_key}",
"accepts": ["{param}", "..."], // the parameter names this axis takes
"bounds": [0.0, 0.0], // valid input range
"nodes": 0 }
],
"nav_per_share": 0.00,
"nav_per_share_{ccy}": 0.00, // same value, currency-suffixed key
"currency": "{USD | CAD | AUD}",
"out_of_grid": false,
"out_of_grid_detail": null, // per axis: "below" | "above" | false
"grid_bounds": { "{axis_key}": [0.0, 0.0], "discount_rate": [0.0, 0.0] },
"interpolation": "{n}-axis multilinear on {m} re-run scenarios",
"disclaimer": "..." // extended when a value was clamped
}
nav_per_share is always accompanied by an explicit currency field
(CAD, USD, or AUD depending on the company's model denomination). Never infer currency from
the commodity type. Read the NAV currency from /catalog or from the
currency field of the /nav-query response itself; do not infer it
from the commodity or the exchange.
# Single commodity axis — name the axis parameter and the rate.
GET /nav-query/{ticker}?gold=4000&rate=0.08
# Multiple commodity axes — name each one. ?row= is refused here.
GET /nav-query/{ticker}?gold=4000&cu=6.5&rate=0.08
# Do not know the axis? Omit it. The response reports what it defaulted.
GET /nav-query/{ticker}?rate=0.08
→ inputs echoes the axis and its value; defaulted_inputs names it
# Single-axis fallback when the parameter name is unknown.
GET /nav-query/{ticker}?row=4000&rate=0.08
Substitute {ticker} with a key from /nav-debug, and read that
ticker's valid input range from its matrix_rows and matrix_cols
before calling. A value outside the grid is clamped to the boundary rather than
extrapolated, and the response reports that per axis in out_of_grid_detail — see
“Out-of-grid inputs are clamped” below.
Interpolation is multilinear over however many axes that ticker's grid carries
— 2n corners, each weighted by the product of its per-axis fractions. It reduces to the
bilinear four-point case only when n = 2. A three-axis ticker interpolates across eight
corners. The 200 response states which was used in its interpolation field, e.g.
"3-axis multilinear on 150 re-run scenarios". Every node is a full model re-run, not a
curve fitted through sampled points.
An input beyond the published grid lands exactly on the edge value rather than
extrapolating past it. That clamp is reported explicitly, because a clamped answer is otherwise
indistinguishable from an interpolated one: same 200, same shape. Three fields carry it, and an
agent should test out_of_grid before treating nav_per_share as an
interpolation:
| Field | Meaning |
|---|---|
out_of_grid | Boolean. True if any supplied input fell outside its axis. |
out_of_grid_detail | Per axis, "below", "above" or false, so you can tell which input was out of range and in which direction. null when nothing was clamped. |
grid_bounds | The [min, max] actually available per axis, including discount_rate. Read this to correct a clamped call. |
When a clamp occurs the disclaimer field is also extended to say the value is a
boundary estimate rather than an interpolation, so a consumer that renders only the disclaimer
still surfaces it.
A multi-axis 200 response carries an axes array — for each axis, its
axis key, the parameter names it accepts, its bounds and its
node count. One call therefore tells an agent everything it needs to make the next call
correctly, including which parameters that ticker takes. Combined with
defaulted_inputs, a bare ?rate=0.08 is a valid discovery call: it returns
a NAV at the model's own deck and describes the surface it came from.
| HTTP | Body | Meaning |
|---|---|---|
| 404 | {"error":"ticker_not_found"} | Ticker not in catalog, or its JSON is not yet uploaded. |
| 404 | {"error":"no_sensitivity_matrix"} | A report exists but the NAV Query API is not enabled for this ticker. /nav-debug reports this in advance as has_sensitivity: false. |
| 400 | {"error":"wrong_axis_param"} | The parameter names no axis on this ticker — e.g. ?gold= on a silver-priced ticker. Self-correcting: the body carries axes with the parameters each axis accepts, plus expected_param. Previously such a call was interpolated against whatever axis existed and returned a plausible, wrong number. |
| 400 | {"error":"ambiguous_axis_param"} | Two parameters claim the same axis, or ?row= was sent to a ticker with more than one commodity axis. The body lists the axes and the parameter to send for each. |
| 400 | {"error":"missing_params"} | No commodity parameter and no discount rate. The body carries the full accepted parameter list and worked examples. |
| 500 | {"error":"malformed_grid"} | The stored grid failed validation. Not caller-correctable; report it. |
Every 400 body is designed to be acted on without re-reading this page: it names the axes, the accepted parameters and, where applicable, the exact parameter to substitute.
AI agents that have been granted access to the Qatom MCP marketplace can discover and call Harcourt tools autonomously, with payment settled automatically from the agent's Qatom wallet. No human approval is required per transaction.
| Field | Value |
|---|---|
| Tool name | harcourt_nav_query_api |
| Tool ID | 77 |
| Price | $1 USD TDN per call |
| MCP server | https://mcp.m.todaq.net/mcp |
| Discovery | Available in Qatom MCP marketplace — search by tool name or by intent |
{
"ticker": "ivn", // lowercase: aris | ivn | itr | vgc | dyl | sa | hl | bnkr | lug | vzla
"commodity_param": "cu", // gold | cu | u3o8 | zn | row
"commodity_price": 6.5, // USD/lb for copper; USD/oz for gold; USD/lb for U3O8
"discount_rate": 0.08 // decimal (0.08 = 8%)
}
Every covered company has its own Qatom tool returning the full NAV PDF report at
$15 USD TDN. Rather than enumerate them here — a list that goes stale the moment a company is
added — discover them in the Qatom marketplace by provider Harcourt Valuations,
or read the authoritative list from the catalog endpoint, where each entry's
report_id is also usable directly:
GET https://reports.harcourtvaluations.ai/catalog
Accept: application/json
POST https://reports.harcourtvaluations.ai/
Content-Type: application/json
{ "report_id": "<report_id from the catalog>" }
To call Qatom-gated tools autonomously, an agent needs:
transfer_to_agent_wallet)The agent sandbox wallet is debited automatically when a tool call succeeds. Revenue is credited to Harcourt's provider Twin in real time.
A free conversational interface to Harcourt's data. Returns plain-language NAV analysis for any covered ticker. No payment required. Useful for quick screening before purchasing a full report or calling the paid API.
https://reports.harcourtvaluations.ai/chat
// Request
{
"messages": [
{ "role": "user", "content": "What's the current P/NAV on Ivanhoe Mines?" }
]
}
// Response (Anthropic messages format)
{
"content": [
{
"type": "text",
"text": "...prose citing that company's current NAV, P/NAV and price deck..."
}
]
}
The chat agent (Klondike Mike) is built on Claude Haiku. The system prompt is generated
server-side from live {ticker}.json files in R2, so it always reflects the
most recent published NAV data. Conversation history should be included in the
messages array for multi-turn sessions (up to 10 turns retained).
When interpreting Harcourt NAV figures, AI agents and models should be aware of:
model_date field. Data
reflects filings, guidance, and metal prices current at that date. Check model currency
before using figures in time-sensitive decisions.currency field is always explicit.Disclaimer: Harcourt Valuations reports and API responses are analytical tools for informational purposes only. They do not constitute investment advice, a formal appraisal, or a recommendation to buy or sell any security. All valuations are model estimates subject to uncertainty. AI agents and models using this data must not present it as investment advice to end users without appropriate disclaimers.