The same source-verified project data the workbench shows, over a versioned REST API and an MCP server for agent tools. The API and MCP server are provided under Team agreements; requests without a key are limited to the same reduced view as the public workbench. This page is the full field-level reference: authentication, tiers, every endpoint and its payload, the data semantics, per-client MCP setup, and code examples.
Present your API key on every request, via either header — Authorization: Bearer sk_... or X-API-Key: sk_.... When both are present, Authorization wins. A missing, malformed, or revoked key is not an error on the versioned /api/v1/* read surface; the request simply resolves to the reduced public view. Keys are issued under Team agreements (bd@nameplatedata.com), shown once at issuance, and stored only as one-way SHA-256 hashes — a lost key is revoked and reissued, never recovered.
Every figure the API returns ties to a source document; claims that could not be verified against a source are refused and recorded rather than published.
| Tier | Payload | Bulk export | Rate limit |
|---|---|---|---|
| Free / anonymous | The reduced public workbench view: identity, status, location, MW presence; dollar amounts, scores, and source/filing detail withheld | — | 60 / hour |
| Team / API | Full read payloads | CSV | 10,000 / hour |
API keys and MCP access are provided under Team agreements. The Pro subscription is workbench-only and does not carry an API key or MCP access; anonymous MCP connections are refused. A request without a key gets the reduced public view at the free rate limit, keyed by client IP.
Six read endpoints plus a bulk export live under /api/v1/. v1 is a stable contract: additive changes ship within it; breaking changes get a new prefix with a deprecation window. Clients should ignore unknown JSON fields. The interactive schema is at /docs (Swagger) and /redoc.
| Endpoint | Min tier | Returns |
|---|---|---|
GET /api/v1/health | free | Liveness, row counts, latest risk-model version. |
GET /api/v1/me | free | Your resolved tier, limits, and auth method. |
GET /api/v1/projects | free | Project summary rows for the full tracked portfolio. |
GET /api/v1/projects/{project_id} | free | The full project dossier: summary, power, costs, financing, filings, timeline, scores, evidence. |
GET /api/v1/market | free | Portfolio-wide market rollup with the disclosed-vs-undisclosed MW split. Free tier gets counts only. |
GET /api/v1/sources/search | free | Full-text search over the approved source corpus. Highlighted excerpts, never full documents. Free tier gets counts only. |
GET /api/v1/export/projects.csv | team | Streaming CSV of the portfolio. |
These apply across every endpoint and are not repeated in the per-endpoint tables below.
tier (free / team) the response was shaped for. On the free tier, paid fields are present but nulled (or list blocks emptied) so the payload keeps its shape.total (matches before the page cut), count (rows in this page), and has_more (boolean, more rows exist beyond this page). filters echoes the filter values the server resolved.null). Companion 0-1 values that are not scores — confidence, percentiles, coverage_percent — are not rescaled.YYYY-MM-DD for filing/estimate dates, full ISO timestamps for retrieved_at / created_at).X-API-Tier and X-RateLimit-Limit / -Remaining / -Reset (seconds to full refill). Over the limit returns 429 with Retry-After (seconds).GET /api/v1/healthLiveness and coverage counts. No query parameters. Served to all tiers.
| Field | Type | Definition |
|---|---|---|
status | string | Service status: ok or unavailable. |
database | string | Backing store identifier (postgres). |
counts | object | Row counts by table (e.g. projects, sources), as integers. |
model_version | string / null | Latest risk-model version behind the current scores, or null if no risk run has been recorded. |
GET /api/v1/meIdentity and entitlement echo. Always returns 200; never gated or rate-limited. No query parameters.
| Field | Type | Definition |
|---|---|---|
authenticated | boolean | Whether a credential resolved to a non-anonymous method. |
method | string | Auth method: api_key, account, or anonymous. |
email | string / null | Account email for the account method; otherwise null. |
tier | string | Resolved tier: free, pro, or team. |
limits | object | The tier's entitlements: requests_per_hour (int), full_payload (bool), bulk_export (bool). |
label | string | Present only for the api_key method: the key's human label (never the secret). |
GET /api/v1/projectsProject summary rows for the full tracked portfolio. No query parameters. Free tier keeps identity, status, and MW presence; scores and third-party MW estimates are nulled.
Response: a JSON array of project summary rows.
| Field | Type | Definition |
|---|---|---|
project_id | string | Stable project identifier; the key for the dossier endpoint. |
canonical_name | string | The project's canonical display name. |
status | string | Lifecycle status (see Data semantics). |
county | string | County the project sits in. |
state | string | Two-letter US state code. |
total_mw | number / null | Operator-disclosed nameplate capacity in MW; null when the operator has not disclosed it. |
energized_mw | number / null | MW disclosed as energized, in MW. |
expected_completion | string / null | Operator-stated expected completion, free text (e.g. "Q1 2027", "late 2028"). |
utility | string / null | Serving utility or interconnecting entity when evidenced. |
project_probability_score | int / null | Model ranking signal (0-100) that the project proceeds. Paid; nulled on free. |
energization_probability_score | int / null | Model ranking signal (0-100) toward energization. Paid; nulled on free. |
delay_risk_score | int / null | Model ranking signal (0-100) for schedule-delay risk. Paid; nulled on free. |
power_realism_score | int / null | Model ranking signal (0-100) for power-plan realism. Paid; nulled on free. |
mw_disclosure_note | string / null | When total_mw is null, the operator's disclosure reason (detail view only). |
mw_estimate | number / null | Third-party MW estimate, kept strictly separate from total_mw (detail view only). Paid. |
mw_estimate_source | string / null | Attribution for mw_estimate. Paid. |
mw_estimate_review_status | string / null | Review status of the third-party estimate. Paid. |
estimated_cost_per_mw | number / null | $/MW derived from the third-party estimate; surfaced only when total_mw is null. Paid. |
depth_tier | string | Derived record-completeness label: deep, partial, or stub. |
depth_tier_label | string | Human label for depth_tier (e.g. "Deep dossier"). |
GET /api/v1/projects/{project_id}The full project dossier. Path parameter project_id (string). An unknown id returns 404. On the free tier the shape is preserved but every paid signal is withheld: dollar-amount blocks are emptied, score blocks keep their shape with every *_score nulled, and analytic panels are dropped.
Top-level structure
| Field | Type | Definition |
|---|---|---|
summary | object | The project summary row (same shape as a /projects row). |
aliases | string[] | Alternate names the project is known by. |
entities | object[] | Involved parties with relationship role and confidence. |
power | object[] | Power / interconnect evidence rows (see below). |
financing | object[] | Financing evidence rows (see below). |
cost_estimates | object[] | Cost-estimate rows (see below). |
regulatory_filings | object[] | Regulatory filing rows (see below). |
timeline | object[] | Timeline event rows (see below). |
gis_features | object[] | Site/location GeoJSON features with a precision label. |
latest_score | object / null | Latest scoring-model run (four headline scores). Paid. |
latest_risk | object / null | Latest risk-model run (seven sub-scores + overall; see below). Paid. |
evidence_depth_tier | object / null | Derived A-D evidence depth tier with its criteria (see below). |
evidence_readiness | object / null | 0-1 readiness score, missing-evidence list, and gap resolutions. |
sources | object[] | The source documents behind the record (id, type, title, url, dates). |
enrichment_findings | object[] | Enrichment findings including holdouts (see Data semantics). |
Additional paid analytic panels ride on the dossier and are withheld on the free tier: capital_stack, cost_benchmark, capex_trend, benchmark, investor_brief, risk_history, model_runs, evidence_impacts, tenant_credit, tenant_offtake, risk_trend, irr_dcf, tax_abatement, transaction_comps, interconnect_queue, community_signal, confidence_bands, anomalies, mw_captures, diligence_checklist.
power[] — power / interconnect evidence
| Field | Type | Definition |
|---|---|---|
source_id | string | Source document backing this power row. |
utility | string / null | Serving utility or interconnecting entity. |
interconnect_mw | number / null | Interconnection capacity in MW. |
backup_generation_mw | number / null | On-site backup generation in MW. |
substation | string / null | Named substation or point of interconnection. |
transmission_dependency | string / null | Transmission upgrade the project depends on. |
power_sources | string[] | Declared power sources (grid, on-site gas, solar, etc.). |
queue_status | string / null | ISO/utility interconnection-queue status when matched. |
notes | string / null | Free-text notes on the power evidence. |
cost_estimates[] — cost evidence
| Field | Type | Definition |
|---|---|---|
cost_estimate_id | int | Identifier for this estimate row. |
source_id / source_url | string / null | Source document and its URL. |
amount_usd | number | Estimate amount in whole USD. |
cost_per_mw | number / null | Amount divided by disclosed MW, in USD/MW. |
estimate_type | string | What kind of estimate (e.g. developer/market-tracker estimate). |
basis | string | Plain-text basis the estimate rests on. |
confidence | number | 0-1 confidence in the estimate (not a 0-100 score). |
estimate_date | string / null | ISO date of the estimate. |
financing[] — financing evidence
| Field | Type | Definition |
|---|---|---|
financing_id | int | Identifier for this financing row. |
source_id / source_url | string / null | Source document and its URL. |
financing_type | string | Raw financing type; rolled up to a category in the market view. |
lender | string / null | Named lender or investor. |
amount_usd | number / null | Financing amount in whole USD. |
financing_date | string / null | ISO date of the financing event. |
phase | string / null | Project phase the financing applies to. |
regulatory_filings[]
| Field | Type | Definition |
|---|---|---|
filing_id | string | Identifier for this filing row. |
source_id | string | Source document backing the filing. |
agency | string | Agency the filing was made with. |
permit_type | string | Type of permit or filing. |
permit_number | string / null | The permit/case number when available. |
status | string | Filing status (e.g. applied, approved). |
applicant | string / null | Named applicant, which may be a third party distinct from the project sponsor. |
filing_date | string / null | ISO filing date. |
timeline[]
| Field | Type | Definition |
|---|---|---|
event_id | string | Identifier for this event. |
event_type | string | What happened (announcement, groundbreaking, filing, etc.). |
event_date | string / null | ISO date of the event. |
source_id | string | Source document backing the event. |
confidence | number | 0-1 confidence in the event. |
evidence_depth_tier
| Field | Type | Definition |
|---|---|---|
tier | string | Depth grade A-D (A = deepest file, D = thin stub). |
label / summary | string | Human label and one-line explanation of the grade. |
criteria | object | Booleans that produced the grade: mw, cost, power, regulatory, approved_source, approved_primary_source. |
latest_risk — risk-model run (paid)
| Field | Type | Definition |
|---|---|---|
model_version | string | Risk-model version that produced these scores. |
overall_risk_score | int | Overall risk ranking signal, 0-100. |
regulatory_risk_score | int | Regulatory sub-score, 0-100. |
power_risk_score | int | Power sub-score, 0-100. |
timing_risk_score | int | Timing sub-score, 0-100. |
financing_risk_score | int | Financing sub-score, 0-100. |
site_risk_score | int | Site sub-score, 0-100. |
counterparty_risk_score | int | Counterparty sub-score, 0-100. |
data_confidence_risk_score | int | Data-confidence sub-score, 0-100. |
explanation_bullets | string[] | Plain-text drivers behind the scores. |
GET /api/v1/marketPortfolio-wide aggregate rollup. No query parameters. Every breakdown carries the disclosed-vs-undisclosed MW split explicitly — undisclosed MW is reported as absent, never imputed. Free / anonymous callers get counts only: MW magnitudes and the model score are nulled, and the risk-band and score-histogram lists are emptied.
totals
| Field | Type | Definition |
|---|---|---|
project_count | int | Total projects in the rollup. |
mw_disclosed_total | number / null | Sum of MW over projects that disclose it, in MW. Paid; nulled on free. |
mw_disclosed_project_count | int | Projects that disclose MW. |
mw_undisclosed_project_count | int | Projects with no disclosed MW. |
mw_weighted_avg_project_probability_score | int / null | MW-weighted average project-probability ranking signal, 0-100. Paid; nulled on free. |
model_versions | string[] | Risk-model version(s) behind the rollup. |
Breakdown row shapes
| Array | Key field(s) | Per-row shape |
|---|---|---|
by_status[] | status | status, project_count, mw_disclosed_sum (number/null), mw_undisclosed_count. |
by_state[] | state | state, project_count, mw_disclosed_sum, mw_undisclosed_count. |
risk_bands[] | band | band (low/medium/high), project_count, mw_disclosed_sum, mw_undisclosed_count. Emptied on free. |
score_distribution[] | bucket_start | bucket_start, bucket_end (0-100 histogram bounds), project_count. Emptied on free. |
by_financing[] | category_key | category_key, category_label, project_count, mw_disclosed_sum, mw_undisclosed_count. |
by_completion_year[] | year | year (int or null for unparseable), project_count, mw_disclosed_sum, mw_undisclosed_count. |
GET /api/v1/sources/searchFull-text search or browse over the approved source corpus. Returns highlighted excerpts, never full documents (a third-party-copyright guard). Free / anonymous callers get counts only.
Query parameters
| Parameter | Type | Default | Filters |
|---|---|---|---|
q | string | — | Full-text query over source titles and body. Omit to browse the newest approved sources. |
source_id | string | — | Return exactly this source (pull context for a citation another surface returned). |
source_type | string | — | Restrict to one source type (see Data semantics). |
project_id | string | — | Restrict to sources linked to this project. |
limit | int | 10 | Max sources to return; clamped to 1-25. |
Response — sources[] row shape
| Field | Type | Definition |
|---|---|---|
source_id | string | Source document identifier. |
source_type | string | Kind of source (see Data semantics). |
title | string | Source title. |
url | string / null | Canonical URL of the source. |
filing_date | string / null | ISO date the source was filed/published. |
retrieved_at | string | ISO timestamp the source was retrieved. |
excerpt | string | Highlighted excerpt (hard-capped); never the full document. |
excerpt_truncated | boolean | Whether the underlying text was longer than the excerpt. |
rank | number / null | Relevance rank when a query was supplied; null in browse mode. |
related_project_ids | string[] | Project ids this source is linked to. |
text_length | int | Character length of the full parsed text behind the excerpt. |
On the free tier the sources rows are removed and replaced with counts_by_source_type and a detail_available note; total and filters are preserved.
GET /api/v1/export/projects.csvStreaming CSV of the full portfolio. Team tier only; any lower tier returns 403. No query parameters. Columns: project_id, canonical_name, status, county, state, total_mw, energized_mw, expected_completion, utility.
Wherever scores appear in this reference, they are model ranking signals on a 0-100 scale, not calibrated probabilities.
Status lifecycle
A project's status moves through the lifecycle below. The five italicised states anchor the benchmark stage ladder in code; rumored, delayed, and cancelled are off-ladder states a project can also carry.
rumored — reported but not confirmed by the operator.announced — publicly announced by the operator or sponsor.permitting — permits or regulatory filings are in progress.under_construction — construction is underway.partially_energized — some capacity is energized.energized — the project is energized / in service.delayed — schedule has slipped materially.cancelled — the project has been cancelled.Evidence depth grades (A-D)
The dossier's evidence_depth_tier is derived live from four core evidence dimensions — MW, a cost estimate, power (utility/interconnect) evidence, a regulatory filing — plus whether an approved source, and an approved primary-tier source, are on file.
Financing rollup categories
The market view rolls each raw financing_type up to one of six categories (category_key → category_label). A project appears in each category it has evidence for; the none bucket is mutually exclusive with the evidence categories.
sponsor_capex — Sponsor-announced capexcorporate_investment — Corporate investmentreal_estate — Real-estate acquisitionproject_financing — Project / construction financingother_disclosed — Other disclosed financingnone — No financing evidenceHoldout finding types
Holdouts are the refusal trail — evidence that was reviewed and deliberately not promoted to booked coverage, each with a recorded reason. Three finding_type values are treated as holdouts:
project_mw_holdout — an MW figure reviewed and not counted (e.g. it mixed PPA capacity with load).capital_candidate_cost_holdout — a capex figure a source implied but never disclosed cleanly.project_entity_holdout — an entity relationship that could not be substantiated.These ride inside the broader enrichment_findings stream, whose queue lanes are ready_to_promote, gap_review, tracked_gap, source_added, and audit_trail.
Risk scores
Risk is a set of ranking signals on a 0-100 scale carrying a model_version. The overall score decomposes into seven sub-scores: regulatory_risk_score, power_risk_score, timing_risk_score, financing_risk_score, site_risk_score, counterparty_risk_score, and data_confidence_risk_score. In the market rollup, risk bands are low (< 34), medium (34-66), and high (≥ 67).
Source types
Each source carries a source_type. The set is open — new types are added as the corpus grows and are not pinned to a fixed enum in code — so treat it as an open string and filter on the values you observe. Common values include news_report, company_filing, and government_record. Use GET /api/v1/sources/search without a query to browse the live set and its counts by type.
The MCP server exposes the database to Claude, Cursor, and other agent clients as nine read-only tools over streamable HTTP at https://nameplatedata.com/mcp/. MCP connections authenticate with a Team API key in a request header; anonymous MCP connections are refused, and every data tool requires the Team tier (only get_access_info answers for any caller).
Each client points at the same endpoint and passes the key as an X-API-Key header.
# Claude Code
claude mcp add --transport http nameplate https://nameplatedata.com/mcp/ \
--header "X-API-Key: sk_..."
# Claude Desktop (claude_desktop_config.json) -- via the mcp-remote bridge.
# Claude Desktop's config file launches local processes only and cannot attach
# headers to a remote URL directly (the Connectors UI cannot either); mcp-remote
# bridges stdio to our endpoint and adds the key header. Requires Node.
# Note: no space after the colon in the header value.
{
"mcpServers": {
"nameplate": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://nameplatedata.com/mcp/",
"--header",
"X-API-Key:sk_..."
]
}
}
}
# Cursor (.cursor/mcp.json)
{
"mcpServers": {
"nameplate": {
"url": "https://nameplatedata.com/mcp/",
"headers": { "X-API-Key": "sk_..." }
}
}
}
# Codex (~/.codex/config.toml)
[mcp_servers.nameplate]
url = "https://nameplatedata.com/mcp/"
headers = { "X-API-Key" = "sk_..." }
| Tool | Key parameters | Returns |
|---|---|---|
search_projects | query, state, status, min_mw, depth_tier, limit | Searches the project portfolio by name, alias, or county. Each row carries project id, name, state, county, status, total MW, evidence depth tier, and overall risk score. |
get_project_dossier | project_id | The full evidence bundle for one project: summary, power and interconnect evidence, cost estimates with source URLs, financing, regulatory filings, timeline events, evidence depth tier, latest risk scores, and this project's holdout findings. |
query_holdouts | state, finding_type, min_mw_proxy, limit | The refusal trail: evidence that was reviewed and deliberately not promoted to coverage, each with a recorded reason and source. |
query_cost_estimates | state, estimate_type, min_amount, limit | The latest cost estimate per project with its basis, confidence, benchmark label, and source URL. |
compare_projects | project_ids | Compares two to five projects column-aligned: MW, cost, computed cost per MW, depth tier, risk dimensions, peer group, and evidence readiness. |
state_rollup | state | Rolls up a state's portfolio: project counts by status and evidence depth tier, announced, queue-matched, and energized MW, cost coverage, and the booked ISO or utility queue context with a citable source. |
market_rollup | — | Rolls up the whole tracked portfolio: totals plus breakdowns by status, state, risk band, probability-score histogram, financing category, and completion year, each with the disclosed-vs-undisclosed MW split. |
search_sources | query, source_id, source_type, project_id, limit | Full-text search over the approved source corpus. Returns highlighted excerpts with source URLs and related project ids, never full documents. Use source_id to pull the context behind a citation another tool returned. |
get_access_info | — | Reports the caller's tier, remaining rate-limit budget, and what each tier unlocks. No database access. |
The MCP tools return the same tier-shaped, receipt-carrying payloads the REST surface does; search_sources shares its exact response builder with GET /api/v1/sources/search.
Natural-language prompts an agent client can answer by chaining these tools:
| Prompt | Tools exercised |
|---|---|
| "Do a deep dive on Google's Project Cannoli in Michigan." | search_projects, get_project_dossier |
| "What do we know vs. not know about Google Papillion? Include what was refused and why." | get_project_dossier, query_holdouts |
| "What did the source documents actually say about Google Red Oak?" | search_sources |
| "Compare Cannoli, Red Oak, and Papillion on capacity, cost, evidence depth, and risk." | compare_projects |
| "How does Cannoli sit in the Michigan picture?" | state_rollup |
An authenticated GET /api/v1/projects in four environments, then a Python example paging /api/v1/sources/search.
curl
curl -H "X-API-Key: sk_..." \ https://nameplatedata.com/api/v1/projects
Python (requests → DataFrame)
import requests, pandas as pd
resp = requests.get(
"https://nameplatedata.com/api/v1/projects",
headers={"X-API-Key": "sk_..."},
timeout=30,
)
resp.raise_for_status()
df = pd.DataFrame(resp.json())
print(df[["project_id", "canonical_name", "state", "total_mw"]].head())
R (httr2 → data.frame)
library(httr2)
resp <- request("https://nameplatedata.com/api/v1/projects") |>
req_headers(`X-API-Key` = "sk_...") |>
req_perform()
projects <- do.call(rbind, lapply(resp_body_json(resp), as.data.frame))
head(projects[c("project_id", "canonical_name", "state", "total_mw")])
Power Query (Excel)
let
Source = Json.Document(
Web.Contents(
"https://nameplatedata.com/api/v1/projects",
[Headers = [#"X-API-Key" = "sk_..."]]
)
),
Table = Table.FromList(Source, Splitter.SplitByNothing()),
Expanded = Table.ExpandRecordColumn(
Table, "Column1",
{"project_id", "canonical_name", "state", "total_mw"}
)
in
Expanded
Python — paging /api/v1/sources/search
import requests
def search_sources(q, page_size=25):
url = "https://nameplatedata.com/api/v1/sources/search"
headers = {"X-API-Key": "sk_..."}
seen = []
while True:
resp = requests.get(
url,
headers=headers,
params={"q": q, "limit": page_size},
timeout=30,
)
resp.raise_for_status()
payload = resp.json()
seen.extend(payload["sources"])
# limit is capped at 25 server-side; stop when the page is not full
if not payload["has_more"]:
break
break # single page here; advance your query/filter to page further
return seen
rows = search_sources("Project Cannoli")
for row in rows:
print(row["source_id"], row["title"], row["url"])
limit is clamped to 25; use has_more to know when more matches exist and narrow q or add source_type / project_id filters to walk a large result set.
The versioned /api/v1/* read endpoints fail open: a missing, invalid, or revoked key is not rejected — the request resolves to the free tier and returns 200 with the reduced view. The status codes below are the ones these surfaces actually return.
| Code | When |
|---|---|
403 | The resolved tier lacks the surface — e.g. GET /api/v1/export/projects.csv below the Team tier, or any legacy /api/* workbench route reached without a Pro/Team credential. |
404 | Unknown project_id on GET /api/v1/projects/{project_id}. |
429 | Rate limit exceeded. Response carries Retry-After (seconds) plus the X-RateLimit-* headers. |
Because keys fail open to the free tier on /api/v1/*, an invalid key does not produce a 401 there — check GET /api/v1/me or the X-API-Tier header to confirm your key resolved as expected. Over MCP, a non-Team caller reaching a data tool gets a JSON refusal (mcp_requires_team_agreement), not an HTTP error.
API keys are issued under Team agreements only — see pricing. Email bd@nameplatedata.com and we'll set you up the same day. Usage is subject to the Terms of Service; the data may not be resold, republished, or used to build a competing dataset.
The public workbench shows the reduced view with no key. For API and MCP access under a Team agreement, email us.