Developers

API & MCP technical reference

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.

Authentication

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.

Tiers & rate limits

TierPayloadBulk exportRate limit
Free / anonymousThe reduced public workbench view: identity, status, location, MW presence; dollar amounts, scores, and source/filing detail withheld60 / hour
Team / APIFull read payloadsCSV10,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.

REST API

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.

EndpointMin tierReturns
GET /api/v1/healthfreeLiveness, row counts, latest risk-model version.
GET /api/v1/mefreeYour resolved tier, limits, and auth method.
GET /api/v1/projectsfreeProject summary rows for the full tracked portfolio.
GET /api/v1/projects/{project_id}freeThe full project dossier: summary, power, costs, financing, filings, timeline, scores, evidence.
GET /api/v1/marketfreePortfolio-wide market rollup with the disclosed-vs-undisclosed MW split. Free tier gets counts only.
GET /api/v1/sources/searchfreeFull-text search over the approved source corpus. Highlighted excerpts, never full documents. Free tier gets counts only.
GET /api/v1/export/projects.csvteamStreaming CSV of the portfolio.

Conventions

These apply across every endpoint and are not repeated in the per-endpoint tables below.

  • Tier field. Every JSON payload echoes the resolved 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.
  • Pagination. List payloads carry 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.
  • Scores. Model scores are published as integers on a 0-100 scale (an unavailable or tier-withheld score is null). Companion 0-1 values that are not scores — confidence, percentiles, coverage_percent — are not rescaled.
  • Units. MW fields are megawatts; dollar amounts are whole USD; dates are ISO-8601 (YYYY-MM-DD for filing/estimate dates, full ISO timestamps for retrieved_at / created_at).
  • Response headers. Every response carries 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/health

Liveness and coverage counts. No query parameters. Served to all tiers.

FieldTypeDefinition
statusstringService status: ok or unavailable.
databasestringBacking store identifier (postgres).
countsobjectRow counts by table (e.g. projects, sources), as integers.
model_versionstring / nullLatest risk-model version behind the current scores, or null if no risk run has been recorded.

GET /api/v1/me

Identity and entitlement echo. Always returns 200; never gated or rate-limited. No query parameters.

FieldTypeDefinition
authenticatedbooleanWhether a credential resolved to a non-anonymous method.
methodstringAuth method: api_key, account, or anonymous.
emailstring / nullAccount email for the account method; otherwise null.
tierstringResolved tier: free, pro, or team.
limitsobjectThe tier's entitlements: requests_per_hour (int), full_payload (bool), bulk_export (bool).
labelstringPresent only for the api_key method: the key's human label (never the secret).

GET /api/v1/projects

Project 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.

FieldTypeDefinition
project_idstringStable project identifier; the key for the dossier endpoint.
canonical_namestringThe project's canonical display name.
statusstringLifecycle status (see Data semantics).
countystringCounty the project sits in.
statestringTwo-letter US state code.
total_mwnumber / nullOperator-disclosed nameplate capacity in MW; null when the operator has not disclosed it.
energized_mwnumber / nullMW disclosed as energized, in MW.
expected_completionstring / nullOperator-stated expected completion, free text (e.g. "Q1 2027", "late 2028").
utilitystring / nullServing utility or interconnecting entity when evidenced.
project_probability_scoreint / nullModel ranking signal (0-100) that the project proceeds. Paid; nulled on free.
energization_probability_scoreint / nullModel ranking signal (0-100) toward energization. Paid; nulled on free.
delay_risk_scoreint / nullModel ranking signal (0-100) for schedule-delay risk. Paid; nulled on free.
power_realism_scoreint / nullModel ranking signal (0-100) for power-plan realism. Paid; nulled on free.
mw_disclosure_notestring / nullWhen total_mw is null, the operator's disclosure reason (detail view only).
mw_estimatenumber / nullThird-party MW estimate, kept strictly separate from total_mw (detail view only). Paid.
mw_estimate_sourcestring / nullAttribution for mw_estimate. Paid.
mw_estimate_review_statusstring / nullReview status of the third-party estimate. Paid.
estimated_cost_per_mwnumber / null$/MW derived from the third-party estimate; surfaced only when total_mw is null. Paid.
depth_tierstringDerived record-completeness label: deep, partial, or stub.
depth_tier_labelstringHuman 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

FieldTypeDefinition
summaryobjectThe project summary row (same shape as a /projects row).
aliasesstring[]Alternate names the project is known by.
entitiesobject[]Involved parties with relationship role and confidence.
powerobject[]Power / interconnect evidence rows (see below).
financingobject[]Financing evidence rows (see below).
cost_estimatesobject[]Cost-estimate rows (see below).
regulatory_filingsobject[]Regulatory filing rows (see below).
timelineobject[]Timeline event rows (see below).
gis_featuresobject[]Site/location GeoJSON features with a precision label.
latest_scoreobject / nullLatest scoring-model run (four headline scores). Paid.
latest_riskobject / nullLatest risk-model run (seven sub-scores + overall; see below). Paid.
evidence_depth_tierobject / nullDerived A-D evidence depth tier with its criteria (see below).
evidence_readinessobject / null0-1 readiness score, missing-evidence list, and gap resolutions.
sourcesobject[]The source documents behind the record (id, type, title, url, dates).
enrichment_findingsobject[]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

FieldTypeDefinition
source_idstringSource document backing this power row.
utilitystring / nullServing utility or interconnecting entity.
interconnect_mwnumber / nullInterconnection capacity in MW.
backup_generation_mwnumber / nullOn-site backup generation in MW.
substationstring / nullNamed substation or point of interconnection.
transmission_dependencystring / nullTransmission upgrade the project depends on.
power_sourcesstring[]Declared power sources (grid, on-site gas, solar, etc.).
queue_statusstring / nullISO/utility interconnection-queue status when matched.
notesstring / nullFree-text notes on the power evidence.

cost_estimates[] — cost evidence

FieldTypeDefinition
cost_estimate_idintIdentifier for this estimate row.
source_id / source_urlstring / nullSource document and its URL.
amount_usdnumberEstimate amount in whole USD.
cost_per_mwnumber / nullAmount divided by disclosed MW, in USD/MW.
estimate_typestringWhat kind of estimate (e.g. developer/market-tracker estimate).
basisstringPlain-text basis the estimate rests on.
confidencenumber0-1 confidence in the estimate (not a 0-100 score).
estimate_datestring / nullISO date of the estimate.

financing[] — financing evidence

FieldTypeDefinition
financing_idintIdentifier for this financing row.
source_id / source_urlstring / nullSource document and its URL.
financing_typestringRaw financing type; rolled up to a category in the market view.
lenderstring / nullNamed lender or investor.
amount_usdnumber / nullFinancing amount in whole USD.
financing_datestring / nullISO date of the financing event.
phasestring / nullProject phase the financing applies to.

regulatory_filings[]

FieldTypeDefinition
filing_idstringIdentifier for this filing row.
source_idstringSource document backing the filing.
agencystringAgency the filing was made with.
permit_typestringType of permit or filing.
permit_numberstring / nullThe permit/case number when available.
statusstringFiling status (e.g. applied, approved).
applicantstring / nullNamed applicant, which may be a third party distinct from the project sponsor.
filing_datestring / nullISO filing date.

timeline[]

FieldTypeDefinition
event_idstringIdentifier for this event.
event_typestringWhat happened (announcement, groundbreaking, filing, etc.).
event_datestring / nullISO date of the event.
source_idstringSource document backing the event.
confidencenumber0-1 confidence in the event.

evidence_depth_tier

FieldTypeDefinition
tierstringDepth grade A-D (A = deepest file, D = thin stub).
label / summarystringHuman label and one-line explanation of the grade.
criteriaobjectBooleans that produced the grade: mw, cost, power, regulatory, approved_source, approved_primary_source.

latest_risk — risk-model run (paid)

FieldTypeDefinition
model_versionstringRisk-model version that produced these scores.
overall_risk_scoreintOverall risk ranking signal, 0-100.
regulatory_risk_scoreintRegulatory sub-score, 0-100.
power_risk_scoreintPower sub-score, 0-100.
timing_risk_scoreintTiming sub-score, 0-100.
financing_risk_scoreintFinancing sub-score, 0-100.
site_risk_scoreintSite sub-score, 0-100.
counterparty_risk_scoreintCounterparty sub-score, 0-100.
data_confidence_risk_scoreintData-confidence sub-score, 0-100.
explanation_bulletsstring[]Plain-text drivers behind the scores.

GET /api/v1/market

Portfolio-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

FieldTypeDefinition
project_countintTotal projects in the rollup.
mw_disclosed_totalnumber / nullSum of MW over projects that disclose it, in MW. Paid; nulled on free.
mw_disclosed_project_countintProjects that disclose MW.
mw_undisclosed_project_countintProjects with no disclosed MW.
mw_weighted_avg_project_probability_scoreint / nullMW-weighted average project-probability ranking signal, 0-100. Paid; nulled on free.
model_versionsstring[]Risk-model version(s) behind the rollup.

Breakdown row shapes

ArrayKey field(s)Per-row shape
by_status[]statusstatus, project_count, mw_disclosed_sum (number/null), mw_undisclosed_count.
by_state[]statestate, project_count, mw_disclosed_sum, mw_undisclosed_count.
risk_bands[]bandband (low/medium/high), project_count, mw_disclosed_sum, mw_undisclosed_count. Emptied on free.
score_distribution[]bucket_startbucket_start, bucket_end (0-100 histogram bounds), project_count. Emptied on free.
by_financing[]category_keycategory_key, category_label, project_count, mw_disclosed_sum, mw_undisclosed_count.
by_completion_year[]yearyear (int or null for unparseable), project_count, mw_disclosed_sum, mw_undisclosed_count.

GET /api/v1/sources/search

Full-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

ParameterTypeDefaultFilters
qstringFull-text query over source titles and body. Omit to browse the newest approved sources.
source_idstringReturn exactly this source (pull context for a citation another surface returned).
source_typestringRestrict to one source type (see Data semantics).
project_idstringRestrict to sources linked to this project.
limitint10Max sources to return; clamped to 1-25.

Response — sources[] row shape

FieldTypeDefinition
source_idstringSource document identifier.
source_typestringKind of source (see Data semantics).
titlestringSource title.
urlstring / nullCanonical URL of the source.
filing_datestring / nullISO date the source was filed/published.
retrieved_atstringISO timestamp the source was retrieved.
excerptstringHighlighted excerpt (hard-capped); never the full document.
excerpt_truncatedbooleanWhether the underlying text was longer than the excerpt.
ranknumber / nullRelevance rank when a query was supplied; null in browse mode.
related_project_idsstring[]Project ids this source is linked to.
text_lengthintCharacter 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.csv

Streaming 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.

Data semantics

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.

  • A — Deep file: MW and a cost estimate and power evidence and an approved primary-source filing.
  • B — Solid file: MW and (a cost estimate or power evidence) and at least one approved source.
  • C — Partial file: at least two of {MW, cost estimate, power evidence, regulatory filing}.
  • D — Thin file: everything else — a thin discovery stub with fewer than two core dimensions.

Financing rollup categories

The market view rolls each raw financing_type up to one of six categories (category_keycategory_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 capex
  • corporate_investment — Corporate investment
  • real_estate — Real-estate acquisition
  • project_financing — Project / construction financing
  • other_disclosed — Other disclosed financing
  • none — No financing evidence

Holdout 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.

MCP server

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).

Client setup

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_..." }

Tools

ToolKey parametersReturns
search_projectsquery, state, status, min_mw, depth_tier, limitSearches 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_dossierproject_idThe 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_holdoutsstate, finding_type, min_mw_proxy, limitThe refusal trail: evidence that was reviewed and deliberately not promoted to coverage, each with a recorded reason and source.
query_cost_estimatesstate, estimate_type, min_amount, limitThe latest cost estimate per project with its basis, confidence, benchmark label, and source URL.
compare_projectsproject_idsCompares two to five projects column-aligned: MW, cost, computed cost per MW, depth tier, risk dimensions, peer group, and evidence readiness.
state_rollupstateRolls 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_rollupRolls 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_sourcesquery, source_id, source_type, project_id, limitFull-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_infoReports 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.

Asking questions

Natural-language prompts an agent client can answer by chaining these tools:

PromptTools 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

Code examples

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.

Errors

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.

CodeWhen
403The 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.
404Unknown project_id on GET /api/v1/projects/{project_id}.
429Rate 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.

Getting a key

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.

Evaluate the coverage.

The public workbench shows the reduced view with no key. For API and MCP access under a Team agreement, email us.