Resources · Data Bank
Integration Guide
Recommended Application Flow
- Discover permitted datasets and selector options using the appropriate catalogue.
- Resolve market-area codes from the release's area list; skip geography for rates.
- Choose a metric subset, observation range and any maturity/horizon filters.
- Request the first page and retain its release identity.
- Follow every continuation using the same credentials and endpoint.
- Interpret values with their units, basis, status, periods and node dimensions.
- Retain provenance for any stored analysis and distinguish later revisions.
Do not query the Data Bank as though it were the Property Valuation API. No property schema, comparable options, lease information or stored-property-data toggle is needed.
JavaScript Example
Run this on a server with an appropriate key. Modern server-side JavaScript runtimes provide fetch; it is not an instruction to embed a key in a browser application.
const base = 'https://api.valtaic.io';
const key = process.env.VALTAIC_API_KEY;
if (!key) throw new Error('VALTAIC_API_KEY is required');
async function getAllSeries(family, selection) {
if (!['markets', 'rates'].includes(family)) throw new Error('Invalid family');
let params = new URLSearchParams(selection);
let releaseId;
const series = new Map();
while (true) {
const response = await fetch(`${base}/v1/${family}/series?${params}`, {
headers: { Authorization: `Bearer ${key}` },
signal: AbortSignal.timeout(30000)
});
const body = await response.text();
if (!response.ok) {
throw new Error(`HTTP ${response.status}; request ${response.headers.get('x-request-id') ?? 'unknown'}`);
}
const page = JSON.parse(body);
releaseId ??= page.release_id;
if (page.release_id !== releaseId) throw new Error('Release changed while paging');
for (const item of page.series) {
if (!series.has(item.series_id)) series.set(item.series_id, { ...item, observations: [] });
series.get(item.series_id).observations.push(...item.observations);
}
if (page.next_cursor === null) return { release_id: releaseId, series: [...series.values()] };
params = new URLSearchParams({ cursor: page.next_cursor });
}
}
const result = await getAllSeries('markets', {
dataset: 'rental_market', area: 'E08000025', property_type: 'flat',
bedroom_group: '2', from: '2025-01', to: '2026-06'
});This minimal example has bounded request timeouts but no automatic retry. Add a bounded retry strategy for transient failures using Errors and Retries. Parse unexpected error content defensively; a gateway response may differ from the service envelope.
Storage and Reproducibility
For each observation, retain at least family, release ID, dataset, selectors, series ID, dimensions, period, value, unit, basis/status and applicable input-window metadata. Keep a release timestamp separately from an observation date.
When refreshing local data, load and validate a complete extraction before marking it current in your application. A failed request should not erase a previously usable dataset. Do not merge half of one release with half of a new release without recording the distinction.
For repeatable analysis across several requests, pin a retained release_id. The current pointer can change between unpinned requests. A market release and a rates release have separate IDs; preserve both when combining them in a report.
Charts and Tables
| Data | Recommended display |
|---|---|
| Rolling sales/activity | Endpoint on the time axis; label the rolling 12-month basis. Never sum overlapping windows. |
| Price bands | Show the band label and that period's GBP bounds. |
| Rent, capital and yield | Show each input date. Do not relabel an older capital estimate with the rental month. |
| Curve | Maturity on the horizontal axis, rate on the vertical axis, snapshot date in the title. |
| Historical curve node | Observation date on the horizontal axis; fix the maturity in the label. |
| Scenario | Projection date/horizon on the horizontal axis; show scenario name and snapshot date. |
| Development deliveries | Show observed cluster-size categories and unclassified coverage; count homes, not sites. |
| Withheld observation | Show a gap labelled under review; retain its reason and review reference. Do not substitute zero or an older value. |
Use percentages and basis points correctly. Keep index values separate from rates. Round monetary estimates and rates to a sensible display precision without changing their stored source values. Do not invent confidence badges or fill missing chart points without explanation.
Concurrency and Reliability
Use modest bounded concurrency rather than launching unbounded requests for every area. Reuse HTTP connections where possible, respect plan limits and back off on throttling. No numeric requests-per-second promise is made here.
Use metrics to avoid retrieving unneeded series and date bounds to avoid downloading unnecessary history. A page size limit is an observation-response limit, not a batch valuation limit. There is no asynchronous job endpoint in this contract.
The service uses Cache-Control: private, no-store. Do not put authenticated responses into a shared HTTP cache. Any application storage or redistribution must follow the applicable licence and retain provenance.
Defensive Client Checklist
- Do not rely on field order or a fixed number of series per page.
- Tolerate additional response metadata while validating required fields and known units.
- Treat unknown status/basis values cautiously rather than defaulting to observed or zero.
- Distinguish missing values, unsupported series, empty ranges and storage/service errors.
- Complete pagination and verify release consistency before displaying a supposedly complete curve or export.
- Protect keys and cursors in logs and browser code.
- Use request IDs for support, not as observation identities.