> ## 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.

# Submit a Forecast Job

> Step-by-step guide - upload CSV, poll status, download results.

## Overview

The forecast endpoint is asynchronous:

1. **POST `/forecast`** - upload your data and receive a `job_id` immediately.
2. **GET `/jobs/{job_id}`** - poll until `status` is `completed` or `failed`.
3. **GET `/jobs/{job_id}/download`** - download the forecast CSV.

This design lets the API handle long-running forecasts (minutes for large
datasets) without blocking the HTTP connection.

***

## Step 1 - Prepare your data

### Required columns

| Column      | Type            | Notes                                     |
| ----------- | --------------- | ----------------------------------------- |
| `item_id`   | string          | Series name, e.g. `store_A`, `SKU-123`    |
| `timestamp` | string/datetime | ISO-8601 preferred: `2024-01-15 09:00:00` |
| `target`    | float           | Observed value at each timestamp          |

### Example CSV

```csv theme={null}
item_id,timestamp,target
store_A,2024-01-01,1500.0
store_A,2024-01-02,1620.0
store_A,2024-01-03,1480.0
store_B,2024-01-01,890.0
store_B,2024-01-02,910.0
store_B,2024-01-03,875.0
```

<Note>
  Each series must have at least **2 historical observations**. More data
  improves accuracy (10-100 points per series is a good target).
</Note>

***

## Step 2 - Submit the job

```bash theme={null}
curl -X POST https://eomer-api-cgeu.onrender.com/forecast \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@data.csv" \
  -F "prediction_length=7" \
  -F "presets=eomer_pulse" \
  -F "item_id_column=item_id" \
  -F "timestamp_column=timestamp" \
  -F "target_column=target"
```

### Form parameters

| Parameter           | Default       | Description                                                        |
| ------------------- | ------------- | ------------------------------------------------------------------ |
| `file`              | -             | CSV or XLSX file (**required**)                                    |
| `prediction_length` | `24`          | Number of future steps to forecast                                 |
| `presets`           | `eomer_pulse` | Model size (see [model list](/quickstart#available-model-presets)) |
| `item_id_column`    | `item_id`     | Column name for series identifier                                  |
| `timestamp_column`  | `timestamp`   | Column name for datetime                                           |
| `target_column`     | `target`      | Column name for the metric                                         |
| `freq`              | auto-detected | Pandas frequency string, e.g. `D`, `H`, `W`                        |

### Response (202 Accepted)

```json theme={null}
{
  "job_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "pending",
  "created_at": "2024-01-15T09:00:00+00:00",
  "prediction_length": 7
}
```

***

## Step 3 - Poll for completion

```bash theme={null}
curl https://eomer-api-cgeu.onrender.com/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Status values

| Status      | Meaning                                     |
| ----------- | ------------------------------------------- |
| `pending`   | Job is queued                               |
| `running`   | Forecast is in progress                     |
| `completed` | Forecast is ready to download               |
| `failed`    | An error occurred - check the `error` field |

### Completed response

```json theme={null}
{
  "job_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "completed",
  "created_at": "2024-01-15T09:00:00+00:00",
  "completed_at": "2024-01-15T09:02:15+00:00",
  "elapsed_seconds": 135.4,
  "num_items": 2,
  "prediction_length": 7,
  "download_url": "/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6/download"
}
```

***

## Step 4 - Download the forecast

```bash theme={null}
curl https://eomer-api-cgeu.onrender.com/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6/download \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o forecast.csv
```

### Output format

```csv theme={null}
item_id,timestamp,mean,0.1,0.5,0.9
store_A,2024-01-08,1560.2,1420.1,1548.9,1698.3
store_A,2024-01-09,1575.8,1433.5,1564.2,1715.7
store_B,2024-01-08,895.1,822.4,892.6,967.8
```

* `mean` - point forecast
* `0.1` / `0.5` / `0.9` - 10th, 50th (median), 90th quantile forecasts

***

## Cleanup

Jobs and output files are automatically deleted after 1 hour (configurable via
`EOMER_JOB_TTL_SECONDS`). To delete a job early:

```bash theme={null}
curl -X DELETE \
  https://eomer-api-cgeu.onrender.com/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns `204 No Content` on success.

***

## Python example (end-to-end)

```python theme={null}
import time
import httpx

API_BASE = "https://eomer-api-cgeu.onrender.com"
API_KEY  = "your-api-key-here"
HEADERS  = {"Authorization": f"Bearer {API_KEY}"}

# 1. Submit
with open("data.csv", "rb") as f:
    resp = httpx.post(
        f"{API_BASE}/forecast",
        headers=HEADERS,
        files={"file": ("data.csv", f, "text/csv")},
        data={"prediction_length": "7", "presets": "eomer_pulse"},
    )
resp.raise_for_status()
job_id = resp.json()["job_id"]
print(f"Submitted job: {job_id}")

# 2. Poll
while True:
    resp = httpx.get(f"{API_BASE}/jobs/{job_id}", headers=HEADERS)
    resp.raise_for_status()
    body = resp.json()
    print(f"Status: {body['status']}")
    if body["status"] in ("completed", "failed"):
        break
    time.sleep(5)

# 3. Download
if body["status"] == "completed":
    resp = httpx.get(f"{API_BASE}/jobs/{job_id}/download", headers=HEADERS)
    resp.raise_for_status()
    with open("forecast.csv", "wb") as f:
        f.write(resp.content)
    print("Forecast saved to forecast.csv")
else:
    print(f"Job failed: {body.get('error')}")
```
