{"openapi":"3.0.0","info":{"title":"Veracle API","version":"0.0.0"},"components":{"schemas":{"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string","example":"veracle-api"},"time":{"type":"string","format":"date-time","example":"2026-06-12T00:00:00.000Z"}},"required":["status","service","time"]},"BulkExport":{"type":"object","properties":{"manifest_id":{"type":"integer"},"dataset":{"type":"string"},"format":{"type":"string"},"schema_version":{"type":"integer"},"r2_uri":{"type":"string"},"content_sha256":{"type":"string"},"row_count":{"type":"integer"},"size_bytes":{"type":"integer"},"as_of":{"type":"string"},"published_at":{"type":"string"}},"required":["manifest_id","dataset","format","schema_version","r2_uri","content_sha256","row_count","size_bytes","as_of","published_at"]},"Residency":{"type":"object","properties":{"data_country":{"type":"string"},"region":{"type":"string"},"provider_data":{"type":"string"},"provider_edge":{"type":"string"},"canonical_store":{"type":"string"},"artifacts_region":{"type":"string"},"future_regions":{"type":"array","items":{"type":"string"}},"enforcement":{"type":"string"}},"required":["data_country","region","provider_data","provider_edge","canonical_store","artifacts_region","future_regions","enforcement"]}},"parameters":{}},"paths":{"/health":{"get":{"summary":"Liveness / health check","tags":["system"],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/ft":{"get":{"summary":"ERC electricity Ft tariff observations (citation-bearing)","tags":["ft"],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}$"},"required":false,"name":"period","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"customer_class","in":"query"},{"schema":{"type":"string"},"required":false,"name":"as_of","in":"query"}],"responses":{"200":{"description":"Ft tariff observations with full provenance envelope","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"data":{"type":"array","items":{"type":"object","properties":{"series_id":{"type":"string","minLength":1,"description":"Canonical series id, e.g. 'th.energy.electricity.ft.general'."},"customer_class":{"type":"string","minLength":1,"description":"Canonical customer class, e.g. 'general', 'residential', 'specific_business'."},"period":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}$","description":"Ft billing period, keyed by its start month (YYYY-MM). ERC sets Ft per 4-month block."},"effective_date":{"type":"string","format":"date","description":"Valid-time start of the Ft period (YYYY-MM-DD)."},"period_end":{"type":"string","format":"date","description":"Inclusive end of the Ft period (YYYY-MM-DD)."},"value":{"type":"number","description":"Canonical Ft value in THB per kWh (satang/100)."},"unit":{"type":"string","minLength":1,"default":"THB/kWh","description":"Canonical unit. Always 'THB/kWh' for Ft."},"ft_rate_satang_per_kwh":{"type":"number","description":"Ft rate as published by ERC, in satang per kWh (สตางค์/หน่วย)."},"as_reported_at":{"type":"string","format":"date-time","description":"Transaction-time: when ERC announced/published this value."},"ingested_at":{"type":"string","format":"date-time","description":"When Veracle ingested it. Set by the store."},"revision_id":{"type":"integer","minimum":1,"description":"Revision number for (series, effective_date). 1 = first reported. Set by the store."},"is_current":{"type":"boolean","description":"Whether this is the current (latest) revision. Set by the store."},"observation_id":{"type":"integer","description":"Canonical observation row id (for the lineage endpoint). Set by the store."},"source_id":{"type":"string","minLength":1,"description":"Publisher id. 'erc' for the authoritative Ft announcement (spec §3.3)."},"source_doc_uri":{"type":"string","minLength":1,"description":"URI of the raw source artifact in the R2 audit store, e.g. 'r2://veracle-raw-artifacts/erc/ft/<sha256>.pdf'. Resolvable for citation."},"source_locator":{"type":"object","properties":{"page":{"type":"integer","minimum":1,"description":"1-based page number in the source PDF."},"bbox":{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4,"description":"Bounding box [left, top, right, bottom] of the matched region."},"table_index":{"type":"integer","minimum":0,"description":"Index of the table on the page, if extracted from a table."},"row":{"type":"integer","minimum":0,"description":"Table row index."},"col":{"type":"integer","minimum":0,"description":"Table column index."},"period_label":{"type":"string","description":"Verbatim period label from the source (Thai retained), e.g. 'ม.ค.–เม.ย. 2568'."},"snippet":{"type":"string","description":"Verbatim source text snippet the value was extracted from."}},"required":["page"],"additionalProperties":false,"description":"Where in the source artifact the value was found (page/bbox/cell), for citation."},"parser_confidence":{"type":"number","minimum":0,"maximum":1,"description":"Extraction confidence 0..1. Records below the quarantine threshold are not published."},"citation":{"type":"string","description":"Human-readable citation string. Built at serve time."}},"required":["series_id","customer_class","period","effective_date","period_end","value","ft_rate_satang_per_kwh","as_reported_at","source_id","source_doc_uri","source_locator","parser_confidence"],"additionalProperties":false,"description":"A single ERC electricity Ft tariff observation — the citation-bearing record returned by the REST endpoint and the get_ft_tariff MCP tool, and the validated contract produced by ingestion. Wraps the bitemporal provenance envelope (spec §2.4/§2.6)."}}},"required":["count","data"]}}}}}}},"/v1/oil":{"get":{"summary":"EPPO daily oil price structures (citation-bearing, all components)","tags":["oil"],"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":false,"name":"date","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"fuel_grade","in":"query"},{"schema":{"type":"string"},"required":false,"name":"as_of","in":"query"}],"responses":{"200":{"description":"Oil price structures with full provenance envelope","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"data":{"type":"array","items":{"type":"object","properties":{"fuel_grade":{"type":"string","minLength":1,"description":"Canonical fuel grade, e.g. 'gasohol_95', 'e20', 'diesel_b7'."},"effective_date":{"type":"string","format":"date","description":"Valid-time date the price structure applies (YYYY-MM-DD). EPPO is daily."},"as_reported_at":{"type":"string","format":"date-time","description":"Transaction-time: when EPPO published this structure."},"ingested_at":{"type":"string","format":"date-time","description":"When Veracle ingested it. Set by the store."},"unit":{"type":"string","minLength":1,"default":"THB/litre","description":"Canonical unit. Always 'THB/litre' for the oil structure."},"components":{"type":"array","items":{"type":"object","properties":{"component":{"type":"string","minLength":1,"description":"Component key, e.g. 'ex_refinery', 'excise_tax', 'municipal_tax', 'oil_fund', 'conservation_fund', 'marketing_margin', 'vat'."},"series_id":{"type":"string","minLength":1,"description":"Canonical series id, e.g. 'th.oil.retail.structure.gasohol_95.ex_refinery'."},"value":{"type":"number","description":"Component value in THB/litre."},"observation_id":{"type":"integer","description":"Canonical observation row id (for lineage). Set by the store."}},"required":["component","series_id","value"],"additionalProperties":false},"minItems":1,"description":"The price-structure components, each a canonical series."},"retail":{"type":"number","description":"Retail pump price in THB/litre (the total the components reconcile to)."},"components_sum":{"type":"number","description":"Sum of the non-retail components in THB/litre."},"residual":{"type":"number","description":"retail - components_sum (THB/litre). Near zero when the structure reconciles."},"reconciles":{"type":"boolean","description":"True when |residual| <= tolerance (spec §3.3 component sum check)."},"tolerance":{"type":"number","default":0.01,"description":"Reconciliation tolerance in THB/litre."},"revision_id":{"type":"integer","minimum":1,"description":"Representative revision for the structure. Set by the store."},"is_current":{"type":"boolean","description":"Whether this is the current (latest) revision. Set by the store."},"source_id":{"type":"string","minLength":1,"description":"Publisher id. 'eppo' for the EPPO oil-price structure."},"source_doc_uri":{"type":"string","minLength":1,"description":"URI of the raw HTML snapshot in the R2 audit store. Resolvable for citation."},"source_locator":{"type":"object","properties":{"page":{"type":"integer","minimum":1,"description":"1-based page (1 for HTML)."},"bbox":{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4,"description":"Bounding box [left, top, right, bottom] if available."},"table_index":{"type":"integer","minimum":0,"description":"Index of the table on the page."},"row":{"type":"integer","minimum":0,"description":"Table row index for the grade."},"selector":{"type":"string","description":"CSS/XPath selector used to locate the table."},"snippet":{"type":"string","description":"Verbatim source text snippet."}},"required":["page"],"additionalProperties":false,"description":"Where in the source artifact the structure was found (page/table/bbox), for citation."},"parser_confidence":{"type":"number","minimum":0,"maximum":1,"description":"Extraction confidence 0..1. Records below the quarantine threshold are not published."},"citation":{"type":"string","description":"Human-readable citation string. Built at serve time."}},"required":["fuel_grade","effective_date","as_reported_at","components","retail","components_sum","residual","reconciles","source_id","source_doc_uri","source_locator","parser_confidence"],"additionalProperties":false,"description":"EPPO daily oil price structure for one fuel grade on one date — the citation-bearing record returned by the REST endpoint and the get_oil_price_structure MCP tool, and the validated contract produced by ingestion. Each component (ex-refinery, taxes, Oil Fund, marketing margin, VAT, retail) is its own canonical series; this record assembles them and asserts they reconcile to retail (spec §2.6/§3.3)."}}},"required":["count","data"]}}}}}}},"/v1/fx":{"get":{"summary":"BOT foreign-exchange reference rates (citation-bearing)","tags":["fx"],"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z]{3}$"},"required":false,"name":"currency","in":"query"},{"schema":{"type":"string","enum":["buying","mid","selling"]},"required":false,"name":"rate_type","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":false,"name":"date","in":"query"},{"schema":{"type":"string"},"required":false,"name":"as_of","in":"query"}],"responses":{"200":{"description":"FX rates with full provenance envelope","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"data":{"type":"array","items":{"type":"object","properties":{"series_id":{"type":"string","minLength":1,"description":"Canonical series id, e.g. 'th.macro.fx.usd.mid'."},"currency_code":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code (uppercase), e.g. 'USD', 'EUR', 'JPY'."},"rate_type":{"type":"string","enum":["buying","mid","selling"],"description":"BOT rate type: buying / mid (average) / selling."},"effective_date":{"type":"string","format":"date","description":"Valid-time date the rate applies (YYYY-MM-DD)."},"as_reported_at":{"type":"string","format":"date-time","description":"Transaction-time: when BOT published this rate."},"ingested_at":{"type":"string","format":"date-time","description":"When Veracle ingested it. Set by the store."},"value":{"type":"number","description":"Rate value in THB, quoted per the `unit` (e.g. THB per 1 USD, or THB per 100 JPY)."},"unit":{"type":"string","minLength":1,"default":"THB/USD","description":"Quote unit, e.g. 'THB/USD' or 'THB/100 JPY'."},"revision_id":{"type":"integer","minimum":1,"description":"Revision number. Set by the store."},"is_current":{"type":"boolean","description":"Whether this is the current (latest) revision. Set by the store."},"observation_id":{"type":"integer","description":"Canonical observation row id (for lineage). Set by the store."},"source_id":{"type":"string","minLength":1,"default":"bot","description":"Publisher id. 'bot' for Bank of Thailand."},"source_doc_uri":{"type":"string","minLength":1,"description":"URI of the raw JSON snapshot in the R2 audit store. Resolvable for citation."},"source_locator":{"type":"object","properties":{"page":{"type":"integer","minimum":1,"description":"1-based page (1 for JSON)."},"response_key":{"type":"string","description":"JSON path into the raw response, e.g. '$.rates.USD.mid'."},"selector":{"type":"string","description":"Selector used to locate the value."},"snippet":{"type":"string","description":"Verbatim source text snippet."}},"required":["page"],"additionalProperties":false,"description":"Where in the source artifact the value was found, for citation."},"parser_confidence":{"type":"number","minimum":0,"maximum":1,"description":"Extraction confidence 0..1. Records below the quarantine threshold are not published."},"citation":{"type":"string","description":"Human-readable citation string. Built at serve time."}},"required":["series_id","currency_code","rate_type","effective_date","as_reported_at","value","source_doc_uri","source_locator","parser_confidence"],"additionalProperties":false,"description":"Bank of Thailand (BOT) foreign-exchange reference rate for one currency and rate type on one date — the citation-bearing record returned by the REST endpoint and the get_fx_rates MCP tool, and the validated contract produced by ingestion. currency_code + rate_type are derived at serve time from the canonical series_id (th.macro.fx.<currency>.<rate_type>); the store keeps the generic §2.4 observation row."}}},"required":["count","data"]}}}}}}},"/v1/macro":{"get":{"summary":"Key Thai macro indicators — policy rate, CPI, GDP (citation-bearing)","tags":["macro"],"parameters":[{"schema":{"type":"string","enum":["policy_rate","cpi_headline","gdp"]},"required":false,"name":"indicator","in":"query"},{"schema":{"type":"string"},"required":false,"name":"as_of","in":"query"}],"responses":{"200":{"description":"Macro indicators with full provenance envelope","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"data":{"type":"array","items":{"type":"object","properties":{"series_id":{"type":"string","minLength":1,"description":"Canonical series id, e.g. 'th.macro.indicator.policy_rate'."},"indicator_code":{"type":"string","enum":["policy_rate","cpi_headline","gdp"],"description":"Indicator key: policy_rate (BOT policy rate), cpi_headline (headline CPI YoY), gdp (real GDP growth YoY)."},"period":{"type":"string","pattern":"^[0-9]{4}-(0[1-9]|1[0-2]|Q[1-4])$","description":"Reporting period: YYYY-MM (monthly) or YYYY-Qx (quarterly)."},"effective_date":{"type":"string","format":"date","description":"Valid-time date = the period start (YYYY-MM-DD)."},"period_end":{"type":"string","format":"date","description":"Last day of the reporting period (YYYY-MM-DD)."},"as_reported_at":{"type":"string","format":"date-time","description":"Transaction-time: when the indicator was published."},"ingested_at":{"type":"string","format":"date-time","description":"When Veracle ingested it. Set by the store."},"value":{"type":"number","description":"Indicator value in the stated unit (e.g. percent)."},"unit":{"type":"string","minLength":1,"default":"percent","description":"Unit of the value, e.g. 'percent' or 'percent_yoy'."},"revision_id":{"type":"integer","minimum":1,"description":"Revision number. Set by the store."},"is_current":{"type":"boolean","description":"Whether this is the current (latest) revision. Set by the store."},"observation_id":{"type":"integer","description":"Canonical observation row id (for lineage). Set by the store."},"source_id":{"type":"string","minLength":1,"default":"bot","description":"Publisher id. 'bot' for Bank of Thailand."},"source_doc_uri":{"type":"string","minLength":1,"description":"URI of the raw JSON snapshot in the R2 audit store. Resolvable for citation."},"source_locator":{"type":"object","properties":{"page":{"type":"integer","minimum":1,"description":"1-based page (1 for JSON)."},"response_key":{"type":"string","description":"JSON path into the raw response, e.g. '$.indicators[0]'."},"selector":{"type":"string","description":"Selector used to locate the value."},"snippet":{"type":"string","description":"Verbatim source text snippet."}},"required":["page"],"additionalProperties":false,"description":"Where in the source artifact the value was found, for citation."},"parser_confidence":{"type":"number","minimum":0,"maximum":1,"description":"Extraction confidence 0..1. Records below the quarantine threshold are not published."},"citation":{"type":"string","description":"Human-readable citation string. Built at serve time."}},"required":["series_id","indicator_code","period","effective_date","period_end","as_reported_at","value","source_doc_uri","source_locator","parser_confidence"],"additionalProperties":false,"description":"A key Thai macro indicator (BOT/official) for one period — the citation-bearing record returned by the REST endpoint and the get_macro_indicators MCP tool, and the validated contract produced by ingestion. indicator_code is derived at serve time from the canonical series_id (th.macro.indicator.<code>); the store keeps the generic §2.4 observation row (effective_date = period start)."}}},"required":["count","data"]}}}}}}},"/v1/observations/{id}/lineage":{"get":{"summary":"Full provenance chain for an observation (spec §3.5)","tags":["provenance"],"parameters":[{"schema":{"type":"integer","nullable":true},"required":false,"name":"id","in":"path"}],"responses":{"200":{"description":"Provenance chain","content":{"application/json":{"schema":{"type":"object","properties":{"observation_id":{"type":"integer"},"series_id":{"type":"string"},"effective_date":{"type":"string"},"as_reported_at":{"type":"string"},"ingested_at":{"type":"string"},"revision_id":{"type":"integer"},"is_current":{"type":"boolean"},"parser_confidence":{"type":"number","nullable":true},"source_doc_uri":{"type":"string"},"source_locator":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"source":{"type":"object","properties":{"source_id":{"type":"string"},"name":{"type":"string","nullable":true},"publisher":{"type":"string","nullable":true},"base_url":{"type":"string","nullable":true}},"required":["source_id","name","publisher","base_url"]}},"required":["observation_id","series_id","effective_date","as_reported_at","ingested_at","revision_id","is_current","parser_confidence","source_doc_uri","source_locator","source"]}}}},"404":{"description":"Observation not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/v1/exports":{"get":{"summary":"List bulk-export Parquet snapshots (spec §2.5)","tags":["exports"],"parameters":[{"schema":{"type":"string","minLength":1},"required":false,"name":"dataset","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"Available export snapshots (most recent first)","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"data":{"type":"array","items":{"$ref":"#/components/schemas/BulkExport"}}},"required":["count","data"]}}}}}}},"/v1/exports/{id}":{"get":{"summary":"Bulk-export snapshot metadata","tags":["exports"],"parameters":[{"schema":{"type":"integer","nullable":true},"required":false,"name":"id","in":"path"}],"responses":{"200":{"description":"Export metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkExport"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/v1/residency":{"get":{"summary":"Data-residency disclosure — where the canonical store + artifacts physically live (spec §0.2)","tags":["system"],"responses":{"200":{"description":"Residency declaration (declarative / software-level)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Residency"}}}}}}}}}