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

# Download Extraction Table Data

> Download extraction table data as a CSV file

Downloads a specific table from an extraction as a CSV file. This endpoint returns the raw CSV data.

## Usage Notes

* The extraction must be in `completed` status to download table data
* This endpoint returns raw CSV data, not a JSON response
* The CSV is formatted with a header row containing column names from the template
* Use the `filter` parameter to download only specific subsets of data
* Use `column_validations` to download only rows with validation issues in specific columns
* Large tables are downloaded in full with a limit of 500,000 rows
* If you need paginated access to large tables, use the [Get Extraction Table Rows](/api-reference/get-extraction-table-rows) endpoint instead

## Request

<ParamField path="id" type="string" required>
  The ID of the extraction.
</ParamField>

<ParamField path="tableKey" type="string" required>
  The key of the table to download.
</ParamField>

<ParamField query="filter" type="string" default="all">
  Filter rows to include in the CSV. Supports comma-separated values for multiple filters.

  * `all` - Include all rows (default)
  * `valid` - Rows that pass all validations
  * `invalid` - Rows that fail at least one validation
  * `error` - Rows with error-severity validations
  * `warn` - Rows with warning-severity validations
  * `info` - Rows with info-severity validations
</ParamField>

<ParamField query="column_validations" type="string">
  Filter to only include rows that have validations in specific columns. Provide column keys as
  comma-separated values (e.g., `column_validations=unit_price,quantity`).
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET https://api.tableflow.com/v2/extractions/uT2bJNWN75YPU95r/tables/line_items/download \
    -H "Authorization: Bearer YOUR_API_KEY" \
    --output line_items.csv
  ```

  ```bash cURL with Filter theme={null}
  curl -X GET https://api.tableflow.com/v2/extractions/uT2bJNWN75YPU95r/tables/line_items/download?filter=valid \
    -H "Authorization: Bearer YOUR_API_KEY" \
    --output valid_line_items.csv
  ```

  ```javascript Node.js theme={null}
  const axios = require("axios");
  const fs = require("fs");

  async function downloadTableData(extractionId, tableKey, filter = "all", outputPath) {
    try {
      const response = await axios.get(
        `https://api.tableflow.com/v2/extractions/${extractionId}/tables/${tableKey}/download`,
        {
          params: { filter },
          headers: {
            Authorization: "Bearer YOUR_API_KEY",
          },
          responseType: "stream",
        }
      );

      // Save the CSV directly to the specified path
      const writer = fs.createWriteStream(outputPath);
      response.data.pipe(writer);

      return new Promise((resolve, reject) => {
        writer.on("finish", () => resolve(outputPath));
        writer.on("error", reject);
      });
    } catch (error) {
      console.error("Error downloading CSV:", error.message);
      throw error;
    }
  }

  // Example usage
  downloadTableData("uT2bJNWN75YPU95r", "line_items", "all", "downloads/line_items.csv")
    .then(filePath => {
      console.log(`CSV file downloaded successfully to: ${filePath}`);
    })
    .catch(error => {
      console.error(`Failed to download CSV file: ${error.message}`);
    });
  ```

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

  def download_table_data(extraction_id, table_key, output_path, filter_type="all"):
      url = f"https://api.tableflow.com/v2/extractions/{extraction_id}/tables/{table_key}/download"
      headers = {
          "Authorization": "Bearer YOUR_API_KEY"
      }
      params = {"filter": filter_type}
      
      # Download the CSV
      response = requests.get(url, headers=headers, params=params)
      response.raise_for_status()
      
      # Save to the specified path
      with open(output_path, 'wb') as f:
          f.write(response.content)
      
      return output_path

  # Example usage
  try:
      file_path = download_table_data(
          "uT2bJNWN75YPU95r",
          "line_items",
          "downloads/line_items.csv"
      )
      print(f"CSV downloaded to: {file_path}")
  except requests.exceptions.HTTPError as e:
      print(f"Error downloading table data: {e}")
  ```
</RequestExample>

## Response

The response is the raw CSV data with a Content-Type header of `text/csv`. The Content-Disposition header will include a filename based on the table key.

For example, if the table key is "line\_items", the response headers might look like:

```
Content-Type: text/csv
Content-Disposition: attachment; filename="line_items.csv"
```

The CSV file will include:

1. A header row with column names
2. Data rows containing the table values
3. All columns defined in the template
4. Only the rows that match the filter criteria (if a filter is applied)

Here's an example of how the CSV content might look:

```
Description,Quantity,Unit Price,Amount
Widget A,5,10.00,50.00
Widget B,3,15.00,45.00
Widget C,2,25.00,50.00
Widget D,1,100.00,100.00
Widget E,10,5.00,50.00
```

## Error Responses

<ResponseField name="error" type="string">
  Error message describing what went wrong.
</ResponseField>

<ResponseExample>
  ```json 400 Bad Request theme={null}
  {
    "error": "Cannot download extraction while in status processing"
  }
  ```

  ```json 400 Bad Request theme={null}
  {
    "error": "Tables over 500000 rows are too large to download directly, please use the /rows pagination endpoint to access the data"
  }
  ```
</ResponseExample>
