> ## Documentation Index
> Fetch the complete documentation index at: https://eomer.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Cost Estimation & Covariates

> Get transparent cost/runtime estimates and enrich forecasts with external data

## Cost Estimation

Before submitting a forecast job, use `POST /estimate` to get a transparent cost and runtime estimate.

### Request

```bash theme={null}
curl -X POST https://api.eomer.ai/estimate \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "n_series": 10,
    "n_timesteps": 365,
    "frequency": "D",
    "forecast_horizon": 30,
    "preset": "eomer_pulse",
    "requested_covariates": ["temperature_2m"],
    "latitude": 52.52,
    "longitude": 13.405
  }'
```

### Request Fields

| Field                  | Type       | Default         | Description                        |
| ---------------------- | ---------- | --------------- | ---------------------------------- |
| `n_series`             | int (>= 1) | *required*      | Number of unique time series       |
| `n_timesteps`          | int (>= 1) | *required*      | Timesteps per series               |
| `frequency`            | string     | `"D"`           | Time frequency: `D`, `W`, `M`, `H` |
| `forecast_horizon`     | int (>= 1) | `24`            | Steps to forecast                  |
| `preset`               | string     | `"eomer_pulse"` | Model preset                       |
| `requested_covariates` | string\[]  | `[]`            | Covariate variables to include     |
| `latitude`             | float      | `null`          | Required for weather covariates    |
| `longitude`            | float      | `null`          | Required for weather covariates    |

### Response

```json theme={null}
{
  "estimated_runtime_seconds": 12.5,
  "estimated_compute_cost_usd": 0.0055,
  "maximum_cost_usd": 0.01375,
  "suggested_quote_usd": 0.00825,
  "backend": "compute worker",
  "breakdown": {
    "base_runtime_s": 15.0,
    "data_runtime_s": 8.76,
    "horizon_runtime_s": 1.8,
    "covariate_runtime_s": 0.45,
    "preset_multiplier": 3.0,
    "total_runtime_s": 12.5,
    "compute_cost_usd": 0.0055
  },
  "available_covariates": [
    "cpi", "fed_funds_rate", "precipitation",
    "relative_humidity_2m", "temperature_2m",
    "treasury_10y", "wind_speed_10m"
  ]
}
```

### What Drives Cost

| Factor               | Impact                                                                                                                        |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **Preset size**      | `eomer_pulse_s` (1x) \< `eomer_pulse_l` (3x) \< `eomer_horizon_s` (5x) \< `eomer_horizon_m` (8x)                              |
| **Data volume**      | Linear scaling with `n_series * n_timesteps`                                                                                  |
| **Forecast horizon** | Minor: \~0.02s per additional step                                                                                            |
| **Covariates**       | Minor: \~0.15s per covariate column                                                                                           |
| **Backend**          | A shared compute node is free; dedicated compute workers bill by runtime at the rate shown in `breakdown.compute_rate_usd_hr` |

***

## Covariates

Enrich your forecasts with external data. The recommended interface is the
structured **`external_covariates`** field — accepted as a JSON string form
field on `POST /forecast`, and as a JSON object in the body of
`POST /forecast/storage-object` and `POST /forecast/batch`.

### Discover available sources

`GET /covariates/catalog` returns every source, its required location key, its
variables, the generated output column names, and which cities/zones are
pre-materialized:

```bash theme={null}
curl https://api.eomer.ai/covariates/catalog -H "Authorization: Bearer $API_KEY"
```

### Sources & variables

| Source        | Entity key                                         | Variables                                                                                                                     |
| ------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `weather`     | `city` *or* `latitude_column` + `longitude_column` | `temperature_2m`, `precipitation`, `wind_speed_10m`, `relative_humidity_2m`, `solar_radiation`, `pressure_msl`, `cloud_cover` |
| `holidays`    | `country_code` (opt. `subdivision_code`)           | `is_public_holiday`, `is_holiday_eve`, `is_holiday_week`                                                                      |
| `fred`        | *(none)*                                           | `fed_funds_rate`, `treasury_10y`, `cpi`                                                                                       |
| `air_quality` | `city`                                             | `pm2_5`, `pm10`, `ozone`, `nitrogen_dioxide`, `sulphur_dioxide`, `carbon_monoxide`                                            |
| `rates`       | *(none — global)*                                  | `breakeven_inflation_10y`, `breakeven_inflation_5y`, `treasury_10y_daily`                                                     |
| `electricity` | `bidding_zone` (`DE_LU`, `DK_1`, `DK_2`, `GB`)     | `load_forecast`, `wind_forecast`, `solar_forecast`                                                                            |

Each enabled variable becomes one extra column named `<prefix>_<variable>`
(e.g. `wx_temperature_2m`, `rate_treasury_10y_daily`, `elec_wind_forecast`)
and is passed to the model as a known future covariate.

### Example: weather by city

```bash theme={null}
curl -X POST https://api.eomer.ai/forecast \
  -H "Authorization: Bearer $API_KEY" \
  -F "file=@sales_data.csv" \
  -F "preset=eomer_pulse" \
  -F "prediction_length=30" \
  -F 'external_covariates={"weather":{"enabled":true,"source":"cds","city":"copenhagen","variables":["temperature_2m","wind_speed_10m"],"point_in_time":true}}'
```

### Example: electricity day-ahead forecasts (renewables-driven prices)

```bash theme={null}
curl -X POST https://api.eomer.ai/forecast \
  -H "Authorization: Bearer $API_KEY" \
  -F "file=@prices.csv" \
  -F "preset=eomer_horizon_s" \
  -F "prediction_length=24" \
  -F 'external_covariates={"electricity":{"enabled":true,"bidding_zone":"DK_1","variables":["wind_forecast","solar_forecast","load_forecast"]}}'
```

### Point-in-time correctness

All archive-backed sources (`weather` via CDS when `source="cds"`,
`air_quality`, `rates`, `electricity`) store `(reference_time, valid_time)`
forecast vintages. With `point_in_time: true` (default) a backtest uses only
the forecast that would have been known at each historical origin — no target
leakage. The public forecast routes currently use the default
`num_val_windows = 1`, which reserves one trailing validation window. Pipeline
configurations that explicitly set `num_val_windows = 0` instead use the latest
issue to supply known covariates beyond the final observation.

> Note: archive-backed sources are scoped to pre-materialized cities/zones —
> check `covered_cities` or `covered_bidding_zones` in the catalog. Unknown
> cities and zones return `400`.

### Legacy fields (deprecated)

The flat form fields `covariates=temperature_2m,...` plus
`latitude`/`longitude` are still accepted and internally mapped onto
`external_covariates.weather`. Prefer the structured field; do not mix both in
one request.

### Error Codes

| Code | Condition                                                          |
| ---- | ------------------------------------------------------------------ |
| 400  | Invalid preset name                                                |
| 400  | Malformed `external_covariates` JSON or unknown city/zone/variable |
| 400  | Both `external_covariates` and legacy `covariates` provided        |
| 401  | Missing or invalid API key                                         |
| 422  | Invalid field values (e.g., `n_series` \< 1)                       |
