# Overview

Welcome to The Forecasting Company API. We expose our own, as well as open-source foundation models,
behind a unified REST API at `https://api.retrocast.com`.

## Quick start

```bash
curl -X POST "https://api.retrocast.com/forecast?model=tabpfn-ts" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "series": [{
      "index": ["2024-01-01","2024-01-02","2024-01-03","2024-01-04","2024-01-05"],
      "target": [125, 120, 140, 135, 133]
    }],
    "horizon": 5,
    "freq": "D",
    "quantiles": [0.1, 0.5, 0.9]
  }'
```

Or with the **Python SDK**:

```bash
pip install theforecastingcompany
```

```python
from theforecastingcompany import TFCClient, TFCModels

client = TFCClient()  # reads TFC_API_KEY from environment

forecast_df = client.forecast(
    train_df,
    model=TFCModels.TabPFN_TS,
    horizon=12,
    freq="W",
    quantiles=[0.1, 0.5, 0.9],
)
```

## Authentication

All API requests require a Bearer token. Obtain your API key at
[https://docs.retrocast.com/settings/api-keys](https://docs.retrocast.com/settings/api-keys).

Include it in every request header:

```
Authorization: Bearer YOUR_API_KEY
```

## Available models

| Model          | Description                              | Covariates?            | Forecast? | Retrocast? |
| -------------- | ---------------------------------------- | ---------------------- | --------- | ---------- |
| `tfc-global`   | Global model for time series             | ✅                     | ✅        | ✅         |
| `tabpfn-ts`    | Foundation model from Uni. of Freiburg   | ✅                     | ✅        | ✅         |
| `moirai-2`     | Salesforce's Moirai v.2                  | ✅                     | ✅        | ✅         |
| `moirai-moe`   | Salesforce's Moirai MoE                  | ✅                     | ✅        | ✅         |
| `timesfm-2`    | Google's TimesFM 2.0                     | Future covariates only | ✅        | ✅         |
| `timesfm-2p5`  | Google's TimesFM 2.5                     | Future covariates only | ✅        | ✅         |
| `chronos-2`    | Amazon's Chronos-2                       | ✅                     | ✅        | ✅         |
| `tirex`        | NXAI's model based on xLSTMs             | ❌                     | ✅        | ✅         |
| `aarima`       | Auto-ARIMA                               | Soon                   | ✅        | ✅         |
| `aets`         | Auto-ETS                                 | Soon                   | ✅        | ✅         |
| `toto-2`       | Datadog's Toto v.2                       | ❌                     | ✅        | ✅         |

### Models that support exogenous variables (covariates)

Only `tabpfn-ts`, `moirai-2`, `chronos-2`, and `moirai-moe` support full exogenous variables.
`timesfm-2` and `timesfm-2p5` support future covariates only.
`tfc-global` supports all covariate types including string covariates and static variables.

### Models that support string covariates

Only `tabpfn-ts` and `tfc-global` support non-numeric (string) covariates. All other models require numeric covariates only.

## Supported frequencies

The `freq` field must be one of:

| Value   | Meaning       |
| ------- | ------------- |
| `5min`  | 5 minutes     |
| `15min` | 15 minutes    |
| `30min` | 30 minutes    |
| `H`     | Hourly        |
| `D`     | Daily         |
| `W`     | Weekly        |
| `M`     | Monthly       |
| `Q`     | Quarterly     |
| `Y`     | Yearly        |

---

# Endpoints

## POST `/forecast`

Perform inference with foundation models. Returns forecasts directly for each request.

### Query parameters

| Parameter | Type   | Required | Default      | Description |
| --------- | ------ | -------- | ------------ | ----------- |
| `model`   | string | Yes      | `tabpfn-ts`  | The forecasting model identifier (see Available Models above) |
| `cloud`   | string | No       | any          | Cloud provider for inference: `gcp`, `aws`, or `oci` |

### Request body

| Field          | Type              | Required | Default             | Description |
| -------------- | ----------------- | -------- | ------------------- | ----------- |
| `series`       | `InputSerie[]`    | Yes      |                     | Array of time series to forecast |
| `horizon`      | integer (1–10000) | Yes      |                     | Number of steps to forecast |
| `freq`         | string            | Yes      |                     | Frequency of the time series (see Supported Frequencies) |
| `context`      | integer or null   | No       | null (auto)         | Number of history steps to use. Auto-set to the smaller of the model max or the length of target |
| `quantiles`    | number[] or null  | No       | `[0.1, 0.9, 0.4, 0.5]` | Quantiles to return in the prediction |
| `covariates`   | `Covariate[]` or null | No   | null                | Additional covariates provided by TFC (holidays, events, etc.) |
| `model_config` | object or null    | No       | null                | Model-specific configuration overrides |

### InputSerie schema

Each series object has the following fields:

| Field                   | Type              | Required | Default | Description |
| ----------------------- | ----------------- | -------- | ------- | ----------- |
| `target`                | number[]          | Yes      |         | Numeric target values (min 1 item) |
| `index`                 | string[]          | Yes      |         | Dates (YYYY-MM-DD), datetimes, or timestamps matching target length |
| `hist_variables`        | object            | No       | `{}`    | Dict of variable name → historical numeric values. Length must match target |
| `future_variables`      | object            | No       | `{}`    | Dict of variable name → future numeric values. Length = target length + horizon |
| `future_variables_index`| string[]          | No       | `[]`    | Dates/timestamps for the future variables |
| `static_variables`      | object            | No       | `{}`    | Dict of variable name → single numeric value (e.g., population, SKU ID) |
| `fcds`                  | integer[] or null | No       | null    | Forecast creation dates as target indexes. Used for backtesting. If null, uses the latest date |
| `only_as_context`       | boolean           | No       | false   | If true, series is used only as context (not forecasted). Only for global models |

### Example: Simple univariate forecast

```json
{
  "series": [
    {
      "index": ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"],
      "target": [125, 120, 140, 135, 133]
    }
  ],
  "horizon": 5,
  "freq": "D",
  "quantiles": [0.1, 0.5, 0.9]
}
```

### Example: Multiple series

```json
{
  "series": [
    {
      "index": ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"],
      "target": [125, 120, 140, 135, 133]
    },
    {
      "index": ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"],
      "target": [500, 300, 200, 100, 200]
    }
  ],
  "horizon": 5,
  "freq": "D",
  "quantiles": [0.1, 0.5, 0.9]
}
```

### Example: Forecast with covariates (exogenous variables)

```json
{
  "series": [
    {
      "index": ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"],
      "target": [125, 120, 140, 135, 133],
      "hist_variables": {
        "temperature": [74, 72, 79, 77, 75]
      },
      "future_variables": {
        "local_attendance_forecast": [125, 75, 200, 122, 123, 150, 100, 120, 121, 119]
      },
      "future_variables_index": [
        "2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05",
        "2024-01-06", "2024-01-07", "2024-01-08", "2024-01-09", "2024-01-10"
      ],
      "static_variables": {
        "Population": 100000
      }
    }
  ],
  "horizon": 5,
  "freq": "D",
  "quantiles": [0.1, 0.5, 0.9],
  "covariates": [
    {
      "type": "holidays",
      "config": { "country": "US" }
    }
  ]
}
```

### Example: With model config (Auto-ARIMA)

```json
{
  "series": [
    {
      "index": ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"],
      "target": [125, 120, 140, 135, 133]
    }
  ],
  "horizon": 5,
  "freq": "D",
  "quantiles": [0.1, 0.5, 0.9],
  "model_config": {
    "model": "aarima",
    "config": { "season_length": 7 }
  }
}
```

### Response

```json
{
  "status": "completed",
  "series": [
    [
      {
        "prediction": {
          "mean": [138.2, 141.5, 139.8, 142.1, 140.3],
          "0.1": [130.1, 132.4, 131.2, 133.5, 131.8],
          "0.5": [138.0, 141.3, 139.6, 141.9, 140.1],
          "0.9": [146.3, 150.6, 148.4, 150.7, 148.8]
        },
        "index": ["2024-01-06", "2024-01-07", "2024-01-08", "2024-01-09", "2024-01-10"],
        "metrics": null
      }
    ]
  ]
}
```

The `series` field is a nested array: `series[i][j]` is the prediction for the i-th input series at the j-th forecast creation date. Each prediction contains:

- `prediction`: dict of quantile → values. Always includes `mean`. Other keys match the requested quantiles.
- `index`: the forecast dates
- `metrics`: accuracy metrics (when the target is known, e.g., during backtesting): `mae`, `mape`, `crps`, `wape`, `scaled_bias`

---

## POST `/forecast-jobs`

Submit a long-running forecast job (e.g., backtesting over many forecast creation dates, or slow statistical models). Returns a `call_id` to poll for results.

### Query parameters

| Parameter | Type   | Required | Default     | Description |
| --------- | ------ | -------- | ----------- | ----------- |
| `model`   | string | Yes      | `tabpfn-ts` | The forecasting model identifier |

### Request body

Same as `/forecast` (see above). The key difference is that `fcds` (forecast creation dates) can be used to request multiple historic forecasts for the same series, useful for backtesting.

### Response

```json
{
  "call_id": "fc-abc123def456"
}
```

Use this `call_id` with the GET endpoint below to retrieve results.

---

## GET `/forecast-jobs/{job_id}`

Retrieve the result of a previously submitted forecast job.

### Path parameters

| Parameter | Type   | Required | Description |
| --------- | ------ | -------- | ----------- |
| `job_id`  | string | Yes      | The job ID returned by POST `/forecast-jobs` |

### Response (job completed)

Same format as the `/forecast` response with `"status": "completed"`.

### Response (job still running)

```json
{
  "status": "in_progress",
  "series": null
}
```

### Error responses

- `403 Forbidden` — you don't have access to this job
- `404 Not Found` — the job ID does not exist

---

## GET `/warmup`

Warmup a model endpoint for better UX in embedded applications. Cold models may take a few seconds on the first inference call; warming up pre-loads them.

### Query parameters

| Parameter | Type   | Required | Default     | Description |
| --------- | ------ | -------- | ----------- | ----------- |
| `model`   | string | Yes      | `tabpfn-ts` | The forecasting model to warmup |
| `cloud`   | string | No       | any         | Cloud provider: `gcp`, `aws`, or `oci` |

---

## GET `/openapi`

Returns the OpenAPI 3.1 specification for this API in JSON format. No authentication required.

---

# Covariates

Covariates are additional variables that can improve forecast accuracy. They come in two forms:

## User-provided covariates

Pass these directly in the `series` objects:

- **`hist_variables`** — variables with values only for the historical period (same length as `target`). Example: recorded temperature.
- **`future_variables`** — variables with values for both history and forecast period. Length = history + horizon. Example: planned promotions, weather forecasts.
- **`static_variables`** — variables that don't change over time. Single numeric value per variable. Example: population, store size.

## TFC-provided covariates

Use the `covariates` array in the request body to automatically add covariates managed by TFC:

### Holidays

```json
{
  "type": "holidays",
  "config": {
    "country": "US",
    "smoothing_method": "auto",
    "window_size": 15,
    "sigma": 7.0,
    "ramp_days": 14
  }
}
```

- `country` (required): 2-character ISO country code (e.g., `US`, `GB`, `FR`, `DE`)
- `smoothing_method`: `auto` (default), `none`, `gaussian`, `exponential`, `ramp`, `flat`
- `window_size`: 1–15 (default 15), should be odd
- `sigma`: standard deviation for Gaussian kernel (default 7.0)
- `ramp_days`: days before/after for ramp (1–35, default 14)

### Events

```json
{
  "type": "events",
  "config": {
    "country": "US"
  }
}
```

- `country` (required): ISO country code or `"Global"`

### Temporal features

```json
{
  "type": "temporal_features",
  "config": {}
}
```

Automatically adds time-based features (day of week, month, etc.).

---

# Model-specific configuration

Some models accept additional configuration via `model_config`:

### Auto-ARIMA (`aarima`)

```json
{
  "model_config": {
    "model": "aarima",
    "config": { "season_length": 7 }
  }
}
```

- `season_length` (integer or null): Override automatic seasonal period detection.

### Auto-ETS (`aets`)

```json
{
  "model_config": {
    "model": "aets",
    "config": { "season_length": 12 }
  }
}
```

- `season_length` (integer or null): Override automatic seasonal period detection.

### Chronos-2 (`chronos-2`)

```json
{
  "model_config": {
    "model": "chronos-2",
    "config": { "is_global": true }
  }
}
```

- `is_global` (boolean, default false): Enable influence across the time-series — useful if all passed-in time-series are related (e.g., same product, different stores).

---

# Python SDK

For a higher-level interface, use the official Python SDK: [`theforecastingcompany`](https://pypi.org/project/theforecastingcompany/).

```bash
pip install theforecastingcompany
```

```python
from theforecastingcompany import TFCClient, TFCModels

client = TFCClient()  # reads TFC_API_KEY env var
```

### Simple forecast

```python
import pandas as pd
from theforecastingcompany import TFCClient, TFCModels

client = TFCClient()

train_df = pd.DataFrame({
    "unique_id": ["store_1"] * 100,
    "ds": pd.date_range("2024-01-01", periods=100, freq="D"),
    "target": range(100),
})

forecast_df = client.forecast(
    train_df,
    model=TFCModels.TabPFN_TS,
    horizon=14,
    freq="D",
    quantiles=[0.1, 0.5, 0.9],
)
```

### Forecast with exogenous variables

```python
forecast_df = client.forecast(
    train_df,
    future_df=future_df,
    model=TFCModels.TFCGlobal,
    horizon=12,
    freq="W",
    static_variables=["region", "store_type"],
    future_variables=["price", "promotion"],
    add_holidays=True,
    country_isocode="US",
)
```

### Cross-validation (backtesting)

```python
cv_df = client.cross_validate(
    train_df,
    model=TFCModels.TabPFN_TS,
    horizon=12,
    freq="W",
    fcds=[pd.Timestamp("2024-06-01"), pd.Timestamp("2024-07-01"), pd.Timestamp("2024-08-01")],
    quantiles=[0.1, 0.5, 0.9],
)
```

### Custom column names

```python
forecast_df = client.forecast(
    my_data,
    model=TFCModels.TimesFM_2,
    horizon=7,
    freq="D",
    id_col="item_id",
    date_col="date",
    target_col="sales",
)
```

### Available TFCModels enum values

- `TFCModels.TFCGlobal` → `"tfc-global"`
- `TFCModels.TabPFN_TS` → `"tabpfn-ts"`
- `TFCModels.Moirai_2` → `"moirai-2"`
- `TFCModels.Moirai_MoE` → `"moirai-moe"`
- `TFCModels.TimesFM_2` → `"timesfm-2"`
- `TFCModels.TimesFM_2p5` → `"timesfm-2p5"`
- `TFCModels.Chronos_2` → `"chronos-2"`
- `TFCModels.Tirex` → `"tirex"`
- `TFCModels.AutoARIMA` → `"aarima"`
- `TFCModels.AutoETS` → `"aets"`

### Data structure requirements

DataFrames must have:
- **`unique_id`** (or custom `id_col`): unique identifier for each time series
- **`ds`** (or custom `date_col`): datetime column
- **`target`** (or custom `target_col`): numeric values to forecast

### Batch size

Models like `chronos-2` and `moirai-2` support batching. Control with `batch_size` (default 256). Increase for speed, decrease if you encounter timeouts.

---

# Error handling

| HTTP Status | Description |
| ----------- | ----------- |
| `200`       | Success     |
| `401`       | Unauthorized — invalid or missing API key |
| `403`       | Forbidden — no access to this resource |
| `404`       | Not found — resource does not exist |
| `422`       | Unprocessable entity — invalid request body or parameters |
| `429`       | Rate limited — too many requests |
| `500`       | Internal server error |

## Support and feedback

Please reach out at `support@theforecastingcompany.com`
