Everything you need to read Veracle's cited, bitemporal reference data from your software or an LLM agent — the provenance model, the full REST API, the remote MCP server, the typed SDKs and the dataset catalog.
The model behind every Veracle datapoint — cited, bitemporal and quarantine-gated.
An AI-ready golden source for Thai & SEA energy and macro reference data. Public-but-painful figures (electricity Ft, oil price structure, FX, macro, gold, equities, bond yields) are normalized into typed series and served — cited and verifiable — to software and LLM agents over REST and a remote MCP server.
Every datapoint carries its provenance inline: source_doc_uri, effective_date, as_reported_at, ingested_at, revision_id, is_current, parser_confidence and a human-readable citation. source_doc_uri resolves to the exact archived source artifact — open it and check the original.
Two time axes: valid-time (effective_date — when a value applies) and transaction-time (as_reported_at / ingested_at — when we learned it). Revisions are append-only; nothing is overwritten. Add ?as_of=YYYY-MM-DD to any read to reconstruct exactly what was known on that date.
ingest → archive raw to R2 → validate (range + period-over-period delta + cross-source reconciliation + sum-checks) → bitemporal store → cite. Cross-source reconciliation holds the Ft to ±0.01 satang (ERC authoritative); oil components must sum to the retail price within tolerance.
A value with low parser-confidence, a failed validation, a reconciliation mismatch or a detected source-layout change is quarantined and never published. The deliberate bias is a false-positive quarantine over publishing a wrong value: a disputed number is held for human review, not served.
This deployment serves representative synthetic fixtures — real ERC / EPPO / BOT data is gated on licensing. The pipeline is fully real: ingestion, content-addressed archival, validation, the bitemporal store, citations, lineage, REST and MCP all behave exactly as in production.
All endpoints are GET unless marked POST · CORS is open (origin *) · auth is anon unless noted. openapi.json
Discover what exists. List and inspect series; filter by domain, country or a free-text query.
/v1/seriesList series; filter domain / country / qanon/v1/series/{id}One series' metadataanoncurl 'https://veracle-api.chaiyaphum.workers.dev/v1/series?domain=commodity.gold'
The generic, cited read of any series. Filter by series_id or series_prefix, a from/to window, and ?as_of for point-in-time.
/v1/observationsCited read of any series; series_id | series_prefix, from, to, as_ofanon/v1/observations/{id}/lineageFull provenance chain to the raw artifactanoncurl 'https://veracle-api.chaiyaphum.workers.dev/v1/observations?series_id=th.macro.fx.usd.mid'
Domain-shaped endpoints that return strongly-typed components (Ft by customer class, oil by grade with all structure components, FX by currency and rate type, macro by indicator).
/v1/ftElectricity Ft; period, customer_classanon/v1/oilOil price structure; date, fuel_gradeanon/v1/fxFX rates; currency, rate_type, dateanon/v1/macroMacro indicator; indicatoranoncurl 'https://veracle-api.chaiyaphum.workers.dev/v1/ft?customer_class=general'
The energy→carbon bridge. Browse the cited emission factors as observations, then POST activity quantities (kWh, litres) with factor series ids to get kgCO₂e back — each result cites the exact factor (TGO, IEA, EU CBAM, DEFRA). Add as_of for point-in-time factors.
/v1/carbon/estimateEnergy→CO₂e; body { items: [{ factor_series, quantity, label }], as_of }anoncurl 'https://veracle-api.chaiyaphum.workers.dev/v1/observations?series_prefix=th.carbon.'
A citation-grounded LLM. Ask in natural language; the answer is grounded in retrieved, cited observations and can't fabricate a number. Env-gated — returns 503 where not enabled.
/v1/askGrounded answer + citations; q, limitkey requiredcurl 'https://veracle-api.chaiyaphum.workers.dev/v1/ask?q=What%20is%20the%20electricity%20Ft%20for%20the%20general%20class%3F'
Bulk Parquet exports with signed downloads, signed-webhook subscriptions, and your own audit trail. Downloads + webhooks require a non-anon principal; the audit trail requires the audit:read scope.
/v1/exportsList bulk Parquet snapshotsanon/v1/exports/{id}/downloadShort-lived signed download URLkey required/v1/webhooksSubscribe to signed eventskey required/v1/auditYour own audit trail (scoped)scopedcurl 'https://veracle-api.chaiyaphum.workers.dev/v1/exports'
Liveness and readiness probes, Prometheus metrics, per-series freshness vs cadence budget, and the declarative data-residency disclosure.
/healthLiveness (cheap)anon/health/readyReadiness; 503 if the DB is unreachableanon/metricsPrometheus metrics (text)anon/v1/freshnessPer-series freshness vs cadence budgetanon/v1/residencyDeclarative data-residency disclosureanon/openapi.jsonMachine-readable OpenAPI documentanoncurl 'https://veracle-api.chaiyaphum.workers.dev/v1/freshness'
Tiers are limits only — anon, free and pro return byte-identical data, provenance and citations. Over-limit requests get a 429. Every response carries X-Veracle-Tier, X-RateLimit-Limit and X-RateLimit-Remaining.
none (by IP)60 / minX-API-Key: vk_…600 / minAuthorization: Bearer … (OAuth)6000 / minThe remote MCP server exposes each dataset as a typed tool, so an agent discovers the catalog and reads cited values directly — no scraping, verifiable citations. It speaks streamable HTTP and is OAuth-protected; for an anonymous dev server the read tools stay permissive.
POST https://veracle-mcp.chaiyaphum.workers.dev/mcp # dev: http://localhost:8788/mcp
list_series↔GET /v1/seriesget_series↔GET /v1/series/{id}get_observations↔GET /v1/observationsget_ft_tariff↔GET /v1/ftget_oil_price_structure↔GET /v1/oilget_fx_rates↔GET /v1/fxget_macro_indicators↔GET /v1/macroget_freshness↔GET /v1/freshnessask_veracle↔GET /v1/askOAuth metadata advertises scopes_supported (ft|oil|fx|macro:read, export:download, webhooks:subscribe, audit:read). Claude Desktop has no native remote transport, so it uses the mcp-remote bridge; Cursor and VS Code take the URL directly.
{
"mcpServers": {
"veracle": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://veracle-mcp.chaiyaphum.workers.dev/mcp"
]
}
}
}A citation-grounded LLM at GET /v1/ask — it answers in plain language but cannot fabricate a number.
Your question is matched to relevant series; the matching cited observations are retrieved and handed to the model as the only allowed evidence.
The model must answer only from the retrieved observations and return their citations. A grounded:false answer is flagged; numbers come from the data, never invented.
Each response returns answer, citations[], model, retrieved, cost_usd and grounded. Click any citation to trace its full lineage to the archived source.
Ask runs only where an LLM provider is configured; otherwise it returns 503 (not enabled). It needs a non-anon principal (an API key) and has its own daily budget.
curl -H 'X-API-Key: vk_…' 'https://veracle-api.chaiyaphum.workers.dev/v1/ask?q=What is the electricity Ft for the general class?'
Both SDKs wrap the REST API and return the shared core-schema types, so responses are validated and carry the full provenance envelope + citation. apiKey / api_key selects the free tier; oauthToken / oauth_token selects pro. They accept an injectable transport for hermetic tests.
@veracle/sdknpm i @veracle/sdk
import { VeracleClient } from "@veracle/sdk";
const veracle = new VeracleClient({
baseUrl: "https://veracle-api.chaiyaphum.workers.dev",
apiKey: "vk_…", // free tier · or oauthToken for pro
});
const ft = await veracle.getFtTariffs({
period: "2025-01",
customer_class: "general",
});
console.log(ft[0].value, ft[0].citation);const res = await veracle.ask( "What is the electricity Ft for the general class?", ); console.log(res.answer); for (const c of res.citations) console.log(c.citation);
A new dataset is nearly free: an ingest fixture plus a series row makes it instantly discoverable, citable and freshness-tracked with zero new serving code. Browse the full live catalog in the Explorer. Browse the full live catalog →
th.energy.electricity.ft.*By customer class (general, residential, …)th.oil.retail.structure.<grade>.<component>Per grade: ex-refinery, taxes, Oil Fund, conservation fund, margin, VAT, retailth.macro.fx.<ccy>.<rate_type>USD/EUR/JPY/GBP/CNY × buying/mid/sellingth.macro.indicator.<code>Policy rate, headline CPI, GDPth.energy.* (reference)Emission factors for energy-cost reasoningth.commodity.gold.*Gold price (GTA reference)th.equity.index.*SET / SET50 / SET100 indicesth.macro.rate.* · th.macro.bond.*MLR/MOR/MRR · government-bond yieldsth.* (LPG/NGV, core CPI, min wage)LPG/NGV, core CPI, minimum wagemy.* · sg.*MY fuel/MYR/OPR/KLCI · SG SGD/CPI/STI/tariffth.derived.energy.effective_cost_indexWeighted Ft+fuel+FX basket (base = 100), carries input observation ids<country>.forecast.<rest>Next-period OLS trend + confidence band — clearly-labelled estimates, never observationsEvery observation returns this provenance envelope — the same shape across REST, MCP, SDKs and Ask.
{
"observation_id": 27,
"series_id": "th.energy.electricity.ft.general",
"value": 0.3672,
"unit": "THB/kWh",
"effective_date": "2025-01-01",
"as_reported_at": "2024-12-15T09:00:00Z",
"ingested_at": "2024-12-16T02:11:00Z",
"revision_id": 1,
"is_current": true,
"parser_confidence": 0.98,
"source_id": "erc",
"source_doc_uri": "r2://veracle-raw-artifacts/erc/ft/8a1f….pdf",
"citation": "ERC electricity Ft — general class, Jan–Apr 2025: 0.3672 THB/kWh. Source: ERC announcement (p.2)."
}GET /v1/observations/{id}/lineage resolves source → archived document; a derived series expands into the input observations it was computed from. Trace any live datapoint in the Explorer →