Conventions

GET /api/v1/sources

List the public sources contributing to the index.

curl https://timber-index.korena.eu/api/v1/sources
{
  "data": [
    {
      "id": "ro-romsilva",
      "name": "Romsilva public auctions",
      "homepage_url": "https://www.rosilva.ro",
      "region_id": "ro-national",
      "source_type": "official_auction",
      "attribution_text": "Source: Romsilva public timber auctions",
      "attribution_url": "https://www.rosilva.ro",
      "is_stale": false,
      "expected_freshness_days": 7
    }
  ]
}

GET /api/v1/species

List active species with bundled BG / EN / DE translations and slugs (so a downstream SEO consumer can render localized pages without a second round-trip).

curl https://timber-index.korena.eu/api/v1/species

GET /api/v1/regions

List active regions with translations, country_code and slugs.

curl https://timber-index.korena.eu/api/v1/regions

GET /api/v1/indexes/species-region

Fetch one aggregated cell (P10 / median / P90 over the last 30 days) for a (species, region, stage) tuple, with the contributing sources and their observation weights.

Query params: species (UUID, required), region (slug, required), stage (defaults to sawlog). Returns 400 if species or region is missing; 200 with data: null and a message if the cell is below the public-index gate.

curl "https://timber-index.korena.eu/api/v1/indexes/species-region\
  ?species=8f2c1a30-1111-4b22-9c33-aaaaaaaaaaaa\
  &region=ro-national\
  &stage=sawlog"
{
  "data": {
    "species_id": "8f2c1a30-1111-4b22-9c33-aaaaaaaaaaaa",
    "region_id": "ro-national",
    "product_stage": "sawlog",
    "p10": 84,
    "median": 112,
    "p90": 148,
    "n_observations": 37,
    "n_sources": 1,
    "avg_confidence": 72,
    "latest_sale": "2026-05-19",
    "computed_at": "2026-05-21T06:00:12.000Z"
  },
  "sources": [
    {
      "source_id": "ro-romsilva",
      "source_name": "Romsilva public auctions",
      "attribution_text": "Source: Romsilva public timber auctions",
      "attribution_url": "https://www.rosilva.ro",
      "weight": 1,
      "latest_sale": "2026-05-19"
    }
  ],
  "meta": {
    "computed_at": "2026-05-21T06:00:12.000Z",
    "license": "Republish allowed with attribution to korena.eu/timber-index",
    "attribution_html": "Data: KORENA Timber Index (timber-index.korena.eu)"
  }
}

GET /api/v1/prices

Raw normalized price rows (most recent first). Optional filters: species, region, stage, limit (default 200). Each row is one normalized observation, not an aggregate.

curl "https://timber-index.korena.eu/api/v1/prices?region=ro-national&limit=50"

GET /api/v1/sitemap.json

Machine-readable index of every publishable (species, region, stage) cell, with n_observations and latest_sale. Used to drive downstream SEO page generation.

curl https://timber-index.korena.eu/api/v1/sitemap.json
{
  "combos": [
    {
      "species_id": "8f2c1a30-1111-4b22-9c33-aaaaaaaaaaaa",
      "region_id": "ro-national",
      "product_stage": "sawlog",
      "n_observations": 37,
      "latest_sale": "2026-05-19"
    }
  ],
  "total": 62
}

License & building on top

You may republish derived figures with attribution to korena.eu/timber-index and a link back. Where a source carries its own attribution requirement, the per-cell sources[] block tells you the exact text.

Building something on top of the index? We’d love to hear about it. There’s no support email yet — open an issue on GitLab and we’ll respond there.