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

# PUT /datasets/{id}/data — Upload Data to a Dataset

> Upload a CSV or gzip-compressed CSV file to add, update, or replace dataset rows. Supports a column manifest, conflict resolution flags, and async processing.

Use this endpoint to load rows into a dataset by uploading a CSV file. The upload is processed asynchronously: the request returns immediately with a process record, and the rows become available in the dataset once the background job completes.

<Note>
  This page is the API reference. For the concepts behind the request — what a manifest is, what gets validated, and how the conflict-resolution flags interact — see the [Uploading Data](/uploading/overview) section.
</Note>

## Authentication

Authenticate using HTTP Basic Auth. Pass your API key as the username and leave the password empty. You must have at least `Write` permission on the target dataset.

## Request

**Method:** `PUT`\
**URL:** `https://api.alphacast.io/datasets/{dataset_id}/data`\
**Content-Type:** `multipart/form-data`

## Path parameters

<ParamField path="dataset_id" type="integer" required>
  The numeric ID of the dataset to upload data into.
</ParamField>

## Form fields

<ParamField body="data" type="file" required>
  The CSV file to upload. Accepts plain `.csv` files or gzip-compressed `.csv.gz` files. The first row must be a header row containing column names.
</ParamField>

<ParamField body="manifest" type="string">
  A JSON string declaring each column's data type and entity flag. Required on the dataset's first upload (or set the manifest beforehand from the web UI). On subsequent uploads it is optional — pass it only when you want to replace the dataset's stored manifest. See the [Manifest reference](/uploading/manifest) for the full schema.
</ParamField>

## Query parameters

<ParamField query="deleteMissingFromDB" type="boolean" default="false">
  When `true`, rows present in the existing dataset but absent from the upload are deleted. Use this to perform a full replacement. Forced to `false` if the dataset's manifest is locked. See [Upload modes](/uploading/validation#upload-modes).
</ParamField>

<ParamField query="onConflictUpdateDB" type="boolean" default="false">
  When `true`, rows whose entity key matches an existing row are updated with the new value. When `false`, the existing value is kept and the upload's value is discarded for those rows.
</ParamField>

<ParamField query="acceptNewColumns" type="boolean" default="false">
  When `true`, columns in the CSV that are not in the dataset's existing schema are added. When `false`, unknown columns cause the upload to fail with `Unknown column(s): ...`. Forced to `false` if the manifest is locked.
</ParamField>

## Response

Returns `201 Created` with a process object describing the background upload job.

<ResponseField name="id" type="string">
  The ID of the upload process. Use this to poll the dataset processes endpoint and inspect status, stats, and any error message.
</ResponseField>

<ResponseField name="status" type="string">
  Initial status — typically `Requested`. Transitions to `Processing` → `Processed` (or `Error`) as the background worker runs. See the [upload lifecycle](/uploading/overview#the-upload-lifecycle).
</ResponseField>

## Example

Upload a CSV file with a manifest:

<RequestExample>
  ```bash cURL theme={null}
  curl -u YOUR_API_KEY: \
    -X PUT https://api.alphacast.io/datasets/123/data \
    -F "data=@gdp_data.csv" \
    -F 'manifest=[{"sourceName":"Date","dataType":"Date","isEntity":true},{"sourceName":"Country","dataType":"String","isEntity":true},{"sourceName":"GDP","dataType":"Decimal","isEntity":false}]'
  ```

  ```python Python theme={null}
  import json
  import requests

  manifest = [
      {"sourceName": "Date", "dataType": "Date", "isEntity": True},
      {"sourceName": "Country", "dataType": "String", "isEntity": True},
      {"sourceName": "GDP", "dataType": "Decimal", "isEntity": False},
  ]

  with open("gdp_data.csv", "rb") as f:
      response = requests.put(
          "https://api.alphacast.io/datasets/123/data",
          auth=("YOUR_API_KEY", ""),
          files={"data": ("gdp_data.csv", f, "text/csv")},
          data={"manifest": json.dumps(manifest)},
      )
  process = response.json()
  ```

  ```javascript Node.js theme={null}
  import fs from "node:fs";

  const manifest = [
    { sourceName: "Date", dataType: "Date", isEntity: true },
    { sourceName: "Country", dataType: "String", isEntity: true },
    { sourceName: "GDP", dataType: "Decimal", isEntity: false },
  ];

  const form = new FormData();
  form.append("data", new Blob([fs.readFileSync("gdp_data.csv")]), "gdp_data.csv");
  form.append("manifest", JSON.stringify(manifest));

  const response = await fetch("https://api.alphacast.io/datasets/123/data", {
    method: "PUT",
    headers: { Authorization: "Basic " + btoa("YOUR_API_KEY:") },
    body: form,
  });
  const process = await response.json();
  ```
</RequestExample>

Upload a gzip-compressed CSV and replace any existing row not present in the file:

```bash theme={null}
curl -u YOUR_API_KEY: \
  -X PUT "https://api.alphacast.io/datasets/123/data?deleteMissingFromDB=true&onConflictUpdateDB=true" \
  -F "data=@gdp_data.csv.gz"
```

Upload a plain CSV and allow new columns to extend the schema:

```bash theme={null}
curl -u YOUR_API_KEY: \
  -X PUT "https://api.alphacast.io/datasets/123/data?acceptNewColumns=true" \
  -F "data=@gdp_data.csv"
```

## Error responses

The API surfaces validation errors via the upload process record (status `Error`, `statusDescription` set to the message). The HTTP response itself uses standard codes:

| Status             | Cause                                                                 |
| ------------------ | --------------------------------------------------------------------- |
| `400 Bad Request`  | The manifest is malformed, or required form fields are missing.       |
| `401 Unauthorized` | Missing or invalid API key.                                           |
| `403 Forbidden`    | You do not have `Write` permission on this dataset.                   |
| `404 Not Found`    | No dataset with the given ID exists or is accessible to your account. |

For row-level validation failures (`Data has not Date column`, duplicate rows, out-of-range Short Integer, etc.) the HTTP call returns `201` with a process record, and the failure surfaces when the process transitions to `Error`. See [Validation rules](/uploading/validation#validation-rules) for the complete list.

<Warning>
  When `deleteMissingFromDB` is `true`, any row in the existing dataset whose key does not appear in the uploaded file is permanently deleted. Verify your file contains every row you wish to keep before setting this flag.
</Warning>

<Note>
  Uploads are processed asynchronously. The API returns immediately with a process object, and the data becomes available in the dataset once the background job completes. Identical re-uploads (same content + same flags as the previous successful run) are detected via a content hash and skipped — see [Idempotency](/uploading/overview#idempotency-identical-content-is-skipped).
</Note>
