# Download Extraction Original File
Source: https://docs.tableflow.com/api-reference/download-original-file
GET /v2/extractions/{id}/download-original
Download the original file that was uploaded for extraction
Downloads the original file that was uploaded for a specific extraction. This endpoint returns the raw file data with the appropriate content type.
## Usage Notes
* This endpoint returns the raw file data, not a JSON response
* The content type will match the original file type (e.g., application/pdf for PDFs)
## Request
The ID of the extraction to download the original file for.
```bash cURL theme={null}
curl -X GET https://api.tableflow.com/v2/extractions/uT2bJNWN75YPU95r/download-original \
-H "Authorization: Bearer YOUR_API_KEY" \
--output original-file.pdf
```
```javascript Node.js theme={null}
const axios = require("axios");
const fs = require("fs");
async function downloadOriginalFile(extractionId, outputPath) {
try {
const response = await axios.get(
`https://api.tableflow.com/v2/extractions/${extractionId}/download-original`,
{
headers: {
Authorization: "Bearer YOUR_API_KEY",
},
responseType: "stream",
}
);
// Save the file 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 file:", error.message);
throw error;
}
}
// Example usage
downloadOriginalFile("uT2bJNWN75YPU95r", "downloads/invoice.pdf")
.then(filePath => {
console.log(`File downloaded successfully to: ${filePath}`);
})
.catch(error => {
console.error(`Failed to download file: ${error.message}`);
});
```
```python Python theme={null}
import requests
def download_original_file(extraction_id, output_path):
"""
Download the original file for an extraction
Args:
extraction_id (str): The ID of the extraction
output_path (str): Path where to save the file
Returns:
str: Path where the file was saved
"""
url = f"https://api.tableflow.com/v2/extractions/{extraction_id}/download-original"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
# Download the file
response = requests.get(url, headers=headers)
response.raise_for_status()
# Save the file to the specified location
with open(output_path, 'wb') as f:
f.write(response.content)
return output_path
# Example usage
try:
file_path = download_original_file("uT2bJNWN75YPU95r", "downloads/invoice.pdf")
print(f"File downloaded successfully to: {file_path}")
except requests.exceptions.HTTPError as e:
print(f"Error downloading file: {e}")
```
## Response
The response is the raw file data with the appropriate Content-Type header. The Content-Disposition header will include the original filename.
For example, if the original file was a PDF named "invoice.pdf", the response headers might look like:
```
Content-Type: application/pdf
Content-Disposition: attachment; filename="invoice.pdf"
```
## Error Responses
Error message describing what went wrong.
```json 400 Bad Request theme={null}
{
"error": "No extraction ID provided"
}
```
# Download Extraction Table Data
Source: https://docs.tableflow.com/api-reference/download-table-data
GET /v2/extractions/{id}/tables/{tableKey}/download
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
The ID of the extraction.
The key of the table to download.
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
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`).
```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}")
```
## 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
Error message describing what went wrong.
```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"
}
```
# Extractions API
Source: https://docs.tableflow.com/api-reference/extractions/overview
Extract structured data from documents using AI
The Extractions API allows you to upload documents and extract structured data using AI-powered templates. TableFlow supports various document types including PDFs, images, spreadsheets, and more.
## Key Features
* **Multi-format support**: Extract from PDFs, images (PNG, JPG), spreadsheets (CSV, Excel), and documents
* **Template-based extraction**: Use pre-configured templates to define what data to extract
* **Automatic template selection**: Let TableFlow choose the best template for your document
* **Table detection**: Automatically detect and extract tables from documents
* **Field validation**: Built-in validation for extracted data
## Common Use Cases
* Invoice processing
* Purchase order extraction
* Form data extraction
* Spreadsheet data transformation
* Document digitization
## Extraction Workflow
Upload your document using the [upload endpoint](/api-reference/upload-file)
TableFlow processes your document using the specified template
Get the extracted data using the [extraction endpoint](/api-reference/get-extraction)
Retrieve table data using the [table rows endpoint](/api-reference/get-extraction-table-rows)
## Extraction Status
Extractions go through several status states:
* `processing` - The document is being processed
* `completed` - Extraction completed successfully
* `failed` - Extraction failed (check the error field)
## Webhooks
You can receive real-time notifications when extractions complete or fail. The webhook events are:
* `extraction.status.completed` - Fired when extraction completes successfully
* `extraction.status.failed` - Fired when extraction fails
Learn more in the [webhooks documentation](/webhooks).
## Next Steps
* [Upload a file](/api-reference/upload-file) to start extracting data
* [Get extraction details](/api-reference/get-extraction) to retrieve extracted fields
* [Download table data](/api-reference/download-table-data) as CSV
# Flows API
Source: https://docs.tableflow.com/api-reference/flows/overview
Orchestrate complex document processing workflows
The Flows API enables you to run pre-configured workflows that combine multiple document processing steps. Flows can include extraction, reconciliation, verification, and review steps to create end-to-end document processing pipelines.
## Key Features
* **Multi-step workflows**: Chain together multiple processing steps
* **Extraction steps**: Extract data from one or multiple documents
* **Reconciliation**: Compare and match data between documents
* **Verification**: Validate extracted data against business rules
* **Review steps**: Add human-in-the-loop approval processes
* **Rerun capability**: Automatically retry failed extractions
## Common Use Cases
* Purchase order to invoice matching
* Multi-document reconciliation workflows
* Document verification with automatic reprocessing
* Human review and approval processes
* Complex data validation pipelines
## Flow Execution Workflow
List available flows using the [flows endpoint](/api-reference/get-flows)
Execute a flow with your documents using the [run flow endpoint](/api-reference/run-flow)
Check flow execution status using the [flow run endpoint](/api-reference/get-flow-run)
Retrieve extraction IDs and results from the completed flow run
## Flow Run Status
Flow runs progress through these status states:
* `processing` - The flow is currently executing
* `review` - The flow is paused pending human review
* `completed` - All flow steps completed successfully
* `failed` - The flow failed (check the error field)
## Webhooks
You can receive real-time notifications when flow runs complete or fail. The webhook events are:
* `flow.run.completed` - Fired when a flow run completes successfully
* `flow.run.failed` - Fired when a flow run fails
The webhook payload includes flow metadata and execution details.
Learn more in the [webhooks documentation](/webhooks).
## Flow Components
### Extraction Steps
Extract data from uploaded documents using AI-powered templates.
### Reconciliation Steps
Compare and match data between multiple extractions (e.g., PO to invoice matching).
### Verification Steps
Validate extracted data against business rules with automatic rerun capability.
### Review Steps
Pause the flow for human review and approval before continuing.
## Next Steps
* [List available flows](/api-reference/get-flows) in your workspace
* [View all flow runs](/api-reference/get-flow-runs) across your workspace
* [View runs for a specific flow](/api-reference/get-flow-runs-by-flow)
* [Run a flow](/api-reference/run-flow) with your documents
* [Check flow run status](/api-reference/get-flow-run) and results
# Extraction
Source: https://docs.tableflow.com/api-reference/get-extraction
GET /v2/extractions/{id}
Get extraction by ID
Retrieves extraction data by ID, including fields, tables, and document information.
## Usage Notes
* This endpoint returns extraction data including all fields
* For tables, it includes up to 100 rows per table (the default pagination limit)
* For tables with more than 100 rows, use the pagination information from each table and the [Get Extraction Table Rows](/api-reference/get-extraction-table-rows) endpoint to retrieve additional rows
## Request
The ID of the extraction to retrieve.
```bash cURL theme={null}
curl -X GET https://api.tableflow.com/v2/extractions/uT2bJNWN75YPU95r \
-H "Authorization: Bearer YOUR_API_KEY"
```
```javascript Node.js theme={null}
const axios = require("axios");
async function getExtraction(extractionId) {
try {
const response = await axios.get(
`https://api.tableflow.com/v2/extractions/${extractionId}`,
{
headers: {
Authorization: "Bearer YOUR_API_KEY",
},
}
);
console.log(response.data);
return response.data;
} catch (error) {
console.error(error);
throw error;
}
}
getExtraction("uT2bJNWN75YPU95r")
.then(extraction => {
console.log(`Extracted data for ${extraction.file_name}`);
});
```
```python Python theme={null}
import requests
def get_extraction(extraction_id):
url = f"https://api.tableflow.com/v2/extractions/{extraction_id}"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
response = requests.get(url, headers=headers)
response.raise_for_status() # Raise exception for 4XX/5XX responses
return response.json()
# Example usage
try:
extraction = get_extraction("uT2bJNWN75YPU95r")
print(f"Extracted data for {extraction['file_name']}")
except requests.exceptions.HTTPError as e:
print(f"Error fetching extraction: {e}")
```
## Response
The unique identifier for the extraction.
The ID of the workspace this extraction belongs to.
The ID of the template used for extraction.
The name of the template used for extraction.
The name of the uploaded file.
The size of the uploaded file in bytes.
Information about the file type.
The file type key (e.g., "document", "spreadsheet").
The file extension (e.g., "pdf", "xlsx").
The file's MIME type.
The current status of the extraction (e.g., "processing", "completed", "failed").
History of status changes for this extraction.
Error message if the extraction failed.
Additional metadata associated with the extraction.
Unix timestamp when the extraction was created.
Unix timestamp when the extraction was last updated.
The extracted data.
Field data extracted from the document.
Map of field keys to their extracted values.
Map of field keys to arrays of validation issues.
The validation that failed.
Severity of the validation issue ("error", "warn", "info").
Error message describing the validation issue.
Map of table keys to their data and pagination information.
Note: This endpoint includes up to 100 rows per table. For tables with more rows, use the pagination information and the [Get Extraction Table Rows](/api-reference/get-extraction-table-rows) endpoint to retrieve additional rows.
Pagination information for this table.
Current offset.
Current limit (typically 100 for the main extraction endpoint).
Total number of rows in the table.
Offset for the next page of results. Will be null if all rows are included.
The applied filter ("all", "valid", "error").
Array of table rows, limited to first 100 rows. For complete access to all rows, use the [Get Extraction Table Rows](/api-reference/get-extraction-table-rows) endpoint.
The row index (0-based).
Map of column keys to their cell values.
Map of column keys to arrays of validation issues.
Statistics about the extraction data.
Statistics about the extracted fields.
Number of fields that passed all validations.
Number of fields that failed at least one validation.
Total number of fields.
Map of table keys to their statistics.
Row statistics for this table.
Number of rows that passed all validations.
Number of rows that failed at least one validation.
Total number of rows.
Column statistics for this table.
Total number of columns.
Map of column keys to their cell statistics.
Number of cells that passed all validations.
Number of cells that failed at least one validation.
Number of cells that are not blank.
The template used at the time of extraction.
```json theme={null}
{
"id": "uT2bJNWN75YPU95r",
"workspace_id": "dk4g1tUg1uHLs8YU",
"template_id": "JlLZVabDjYWzu7C9",
"template_name": "Invoice Template",
"file_name": "acme-invoice-apr2023.pdf",
"file_size": 245872,
"file_type": {
"key": "document",
"extension": "pdf",
"mime_type": "application/pdf"
},
"status": "completed",
"status_history": [
{
"status": "processing",
"time": 1682366228,
"message": "File uploaded"
},
{
"status": "completed",
"time": 1682366240,
"message": "Extraction completed"
}
],
"created_at": 1682366228,
"updated_at": 1682366240,
"data": {
"fields": {
"values": {
"invoice_number": "INV-20230415",
"invoice_date": "2023-04-15",
"customer_name": "Acme Corporation",
"payment_terms": "Net 30",
"total_amount": "1245.75"
},
"validations": {}
},
"tables": {
"line_items": {
"pagination": {
"offset": 0,
"limit": 100,
"total": 2,
"next_offset": null,
"filter": "all"
},
"rows": [
{
"index": 0,
"values": {
"description": "Ergonomic Office Chair",
"quantity": "1",
"unit_price": "249.99",
"amount": "249.99"
},
"validations": {}
},
{
"index": 1,
"values": {
"description": "Wireless Keyboard",
"quantity": "2",
"unit_price": "59.95",
"amount": "119.90"
},
"validations": {}
}
]
}
}
},
"stats": {
"fields": {
"valid": 5,
"invalid": 0,
"total": 5
},
"tables": {
"line_items": {
"rows": {
"valid": 2,
"invalid": 0,
"total": 2
},
"columns": {
"total": 4
}
}
}
},
"template": {
"id": "JlLZVabDjYWzu7C9",
"name": "Invoice Template",
"fields": [
{
"key": "invoice_number",
"name": "Invoice Number",
"data_type": "string"
}
],
"tables": [
{
"key": "line_items",
"name": "Line Items",
"columns": [
{
"key": "description",
"name": "Description",
"data_type": "string"
}
]
}
]
}
}
```
## Error Responses
Error message describing what went wrong.
```json 400 Bad Request theme={null}
{
"error": "No extraction ID provided"
}
```
# Get Extraction Table Rows
Source: https://docs.tableflow.com/api-reference/get-extraction-table-rows
GET /v2/extractions/{id}/tables/{tableKey}/rows
Get paginated rows from an extraction table
Retrieves paginated rows from a specific table in an extraction. This endpoint is useful for accessing large tables efficiently.
## Usage Notes
* Use pagination to retrieve rows from large tables
* Row indexes are 0-based, meaning the first row has an index of 0
* When no `offset` or `limit` is provided, defaults to offset 0 and limit 100
* Multiple filters can be combined using comma-separated values (e.g., `filter=error,warn`)
## Request
The ID of the extraction.
The key of the table to retrieve rows from.
The number of rows to skip. Minimum value is 0.
The maximum number of rows to return. Minimum value is 1, maximum value is
1000\.
Filter rows by status or validation state. Supports comma-separated values for multiple filters.
* `all` - Return 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
Filter to only return rows that have validations in specific columns. Provide column keys as
comma-separated values (e.g., `column_validations=unit_price,quantity`). Only rows with
validation issues in any of the specified columns will be returned.
```bash cURL theme={null}
curl -X GET https://api.tableflow.com/v2/extractions/uT2bJNWN75YPU95r/tables/line_items/rows?offset=0&limit=100 \
-H "Authorization: Bearer YOUR_API_KEY"
```
```javascript Node.js theme={null}
const axios = require("axios");
async function getTableRows(extractionId, tableKey, offset, limit, filter = "all") {
try {
const response = await axios.get(
`https://api.tableflow.com/v2/extractions/${extractionId}/tables/${tableKey}/rows`,
{
params: {
offset,
limit,
filter,
},
headers: {
Authorization: "Bearer YOUR_API_KEY",
},
}
);
return response.data;
} catch (error) {
console.error(error);
throw error;
}
}
// Example usage
getTableRows("uT2bJNWN75YPU95r", "line_items", 0, 100)
.then(result => {
console.log(`Fetched ${result.rows.length} rows out of ${result.pagination.total}`);
// Process the rows
result.rows.forEach(row => {
console.log(`Row ${row.index}: ${row.values.description}`);
});
});
```
```python Python theme={null}
import requests
def get_table_rows(extraction_id, table_key, offset, limit, filter_type="all"):
url = f"https://api.tableflow.com/v2/extractions/{extraction_id}/tables/{table_key}/rows"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
params = {
"offset": offset,
"limit": limit,
"filter": filter_type
}
response = requests.get(url, headers=headers, params=params)
response.raise_for_status() # Raise exception for 4XX/5XX responses
return response.json()
# Example usage
try:
result = get_table_rows("uT2bJNWN75YPU95r", "line_items", 0, 100)
print(f"Fetched {len(result['rows'])} rows out of {result['pagination']['total']}")
# Process the rows
for row in result['rows']:
print(f"Row {row['index']}: {row['values']['description']}")
except requests.exceptions.HTTPError as e:
print(f"Error fetching table rows: {e}")
```
## Response
Pagination information.
Current offset.
Current limit.
Total number of rows in the table.
Offset for the next page of results. Will be null on the last page.
The applied filter (e.g., "all", "valid", "invalid", "error").
Array of table rows.
The row index (0-based).
Map of column keys to their cell values.
The value of this cell.
Map of column keys to arrays of validation issues.
Array of validation issues for the cell.
The validation that failed.
Severity of the validation issue ("error", "warn", "info").
Error message describing the validation issue.
```json theme={null}
{
"pagination": {
"offset": 0,
"limit": 100,
"total": 3,
"next_offset": null,
"filter": "all"
},
"rows": [
{
"index": 0,
"values": {
"description": "Ergonomic Office Chair",
"quantity": "1",
"unit_price": "249.99",
"amount": "249.99"
},
"validations": {}
},
{
"index": 1,
"values": {
"description": "Wireless Keyboard",
"quantity": "2",
"unit_price": "59.95",
"amount": "119.90"
},
"validations": {}
},
{
"index": 2,
"values": {
"description": "27-inch Monitor",
"quantity": "2",
"unit_price": "329.99",
"amount": "659.98"
},
"validations": {}
}
]
}
```
## Error Responses
Error message describing what went wrong.
```json 400 Bad Request theme={null}
{
"error": "The parameter 'filter' contains invalid value: unknown"
}
```
# List Extractions
Source: https://docs.tableflow.com/api-reference/get-extractions
GET /v2/extractions
Get a paginated list of extractions in your workspace
Retrieves a paginated list of extractions in your workspace. Returns a summary of each extraction including status, template, and file information.
## Usage Notes
* Results are ordered by creation date (newest first)
* Use `template_id` to filter extractions by a specific template
* For full extraction data including fields and tables, use the [Get Extraction](/api-reference/get-extraction) endpoint
## Request
Filter extractions by a specific template ID.
Maximum number of extractions to return. Maximum value is 1000.
Number of extractions to skip for pagination.
```bash cURL theme={null}
curl -X GET "https://api.tableflow.com/v2/extractions?limit=50&offset=0" \
-H "Authorization: Bearer YOUR_API_KEY"
```
```javascript Node.js theme={null}
const axios = require("axios");
async function getExtractions(options = {}) {
try {
const response = await axios.get(
"https://api.tableflow.com/v2/extractions",
{
params: {
template_id: options.templateId,
limit: options.limit || 100,
offset: options.offset || 0,
},
headers: {
Authorization: "Bearer YOUR_API_KEY",
},
}
);
return response.data;
} catch (error) {
console.error(error);
throw error;
}
}
// Example: list recent extractions
getExtractions({ limit: 50 }).then((result) => {
console.log(`Found ${result.total} extractions`);
result.extractions.forEach((ext) => {
console.log(`${ext.id} - ${ext.status} - ${ext.file_info.file_name}`);
});
});
```
```python Python theme={null}
import requests
def get_extractions(template_id=None, limit=100, offset=0):
url = "https://api.tableflow.com/v2/extractions"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
params = {
"limit": limit,
"offset": offset
}
if template_id:
params["template_id"] = template_id
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
return response.json()
# Example: list recent extractions
result = get_extractions(limit=50)
print(f"Found {result['total']} extractions")
for ext in result["extractions"]:
print(f"{ext['id']} - {ext['status']} - {ext['file_info']['file_name']}")
```
## Response
Array of extraction summary objects.
The unique identifier for the extraction.
The current status of the extraction (`processing`, `completed`, or `failed`).
The ID of the template used for the extraction.
Custom metadata associated with the extraction.
Unix timestamp when the extraction was created.
Unix timestamp when the extraction was last updated.
Basic information about the uploaded file.
The name of the uploaded file.
The file type key (e.g., `pdf`, `csv`, `xlsx`).
Total number of extractions matching the query.
The limit applied to this request.
The offset applied to this request.
```json theme={null}
{
"extractions": [
{
"id": "uT2bJNWN75YPU95r",
"status": "completed",
"template_id": "JlLZVabDjYWzu7C9",
"metadata": {
"user_id": "123",
"reference": "INV-2023-04-15"
},
"created_at": 1682366228,
"updated_at": 1682366240,
"file_info": {
"file_name": "acme-invoice-apr2023.pdf",
"file_type": "pdf"
}
},
{
"id": "xK9mPqR3vW7nB2cD",
"status": "processing",
"template_id": "JlLZVabDjYWzu7C9",
"metadata": null,
"created_at": 1682366300,
"updated_at": 1682366300,
"file_info": {
"file_name": "quarterly-report.xlsx",
"file_type": "xlsx"
}
}
],
"total": 47,
"limit": 100,
"offset": 0
}
```
# Get Flow Run
Source: https://docs.tableflow.com/api-reference/get-flow-run
GET /v2/flows/runs/{id}
Get the status and details of a flow run
Retrieves detailed information about a specific flow run, including its current status and execution history.
## Usage Notes
* The response includes the flow definition for context
* Use this endpoint to monitor flow execution progress
* Poll this endpoint to check when a flow completes
* The drive\_files object contains links to Google Drive exports (if enabled)
## Request
The ID of the flow run
## Response
```json theme={null}
{
"id": "Wp7kRnT2mX4vQ9bL",
"flow_id": "dk4g1tUg1uHLs8YU",
"workspace_id": "uT2bJNWN75YPU95r",
"status": "completed",
"status_history": [
{
"status": "processing",
"time": 1682366228,
"message": "Flow started via api"
},
{
"status": "completed",
"time": 1682366258,
"message": "Flow completed successfully"
}
],
"error": null,
"metadata": {
"customer_id": "12345",
"order_number": "PO-2024-001"
},
"trigger_method": "api",
"start_time": 1682366228,
"end_time": 1682366258,
"duration": 30000,
"drive_files": {
"reconciliation": {
"file_id": "1ABC123DEF456",
"mime_type": "application/vnd.google-apps.spreadsheet",
"sheets": [
{
"sheet_id": 0,
"title": "Reconciliation Results"
}
]
}
},
"flow": {
"id": "dk4g1tUg1uHLs8YU",
"workspace_id": "uT2bJNWN75YPU95r",
"name": "PO to Invoice Reconciliation",
"description": "Match purchase orders with invoices and verify totals",
"steps": [
{
"id": "step_1",
"title": "Extract Purchase Order",
"type": "extraction"
},
{
"id": "step_2",
"title": "Extract Invoice",
"type": "extraction"
},
{
"id": "step_3",
"title": "Reconcile Documents",
"type": "reconciliation"
}
],
"active": true
},
"created_at": 1682366228,
"updated_at": 1682366258
}
```
```bash cURL theme={null}
curl --request GET \
--url https://api.tableflow.com/v2/flows/runs/Wp7kRnT2mX4vQ9bL \
--header 'Authorization: Bearer YOUR_API_KEY'
```
```python Python theme={null}
import requests
response = requests.get(
"https://api.tableflow.com/v2/flows/runs/Wp7kRnT2mX4vQ9bL",
headers={
"Authorization": "Bearer YOUR_API_KEY"
}
)
flow_run = response.json()
```
```javascript JavaScript theme={null}
const response = await fetch("https://api.tableflow.com/v2/flows/runs/Wp7kRnT2mX4vQ9bL", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY"
}
});
const flowRun = await response.json();
```
The unique identifier for the flow run
The ID of the flow being executed
The workspace ID
Current status of the flow run
* `processing` - Flow is currently executing
* `review` - Flow is paused for human review
* `completed` - Flow completed successfully
* `failed` - Flow failed (check error field)
History of status changes
The status value
Unix timestamp of the status change
Description of the status change
Error message if the flow run failed
Custom metadata provided when running the flow
How the flow was triggered: api or manual
Unix timestamp when the flow run started
Unix timestamp when the flow run completed
Duration of the flow run in milliseconds
Google Drive files created during the flow (if Google Drive integration is enabled).
History of flow execution attempts, including retries. Each attempt contains
details about step executions for that attempt.
The current attempt number (1-based). Increments when a flow is rerun.
Map of file field keys to the files that were uploaded for this flow run,
including file names, types, and sizes.
Step execution details for all attempts. Each step execution includes
the step ID, status, timing, and any outputs or errors.
The flow definition at the time of execution (included for context).
Unix timestamp when the flow run was created
Unix timestamp when the flow run was last updated
# Get Flow Runs
Source: https://docs.tableflow.com/api-reference/get-flow-runs
GET /v2/flows/runs
Get a list of all flow runs in your workspace
Retrieves a paginated list of flow runs with optional filtering by flow ID or status.
## Usage Notes
* Results are paginated with a default limit of 100
* Results are ordered by creation date (newest first)
* Use filters to narrow down results by flow or status
* The response includes complete flow run details
## Request
Filter by a specific flow ID to only return runs for that flow.
Filter by status. Valid values: `processing`, `review`, `completed`, or `failed`.
Maximum number of results to return. Maximum value is 1000.
Number of results to skip for pagination.
## Response
```json theme={null}
{
"flow_runs": [
{
"id": "Wp7kRnT2mX4vQ9bL",
"flow_id": "dk4g1tUg1uHLs8YU",
"workspace_id": "uT2bJNWN75YPU95r",
"status": "completed",
"status_history": [
{
"status": "processing",
"time": 1682366228,
"message": "Flow started via api"
},
{
"status": "completed",
"time": 1682366258,
"message": "Flow completed successfully"
}
],
"error": null,
"metadata": {
"customer_id": "12345",
"order_number": "PO-2024-001"
},
"trigger_method": "api",
"start_time": 1682366228,
"end_time": 1682366258,
"duration": 30000,
"drive_files": {},
"created_at": 1682366228,
"updated_at": 1682366258
},
{
"id": "hN3cYs8fKj6pA5wD",
"flow_id": "dk4g1tUg1uHLs8YU",
"workspace_id": "uT2bJNWN75YPU95r",
"status": "processing",
"status_history": [
{
"status": "processing",
"time": 1682366328,
"message": "Flow started via api"
}
],
"error": null,
"metadata": {
"customer_id": "67890"
},
"trigger_method": "api",
"start_time": 1682366328,
"end_time": null,
"duration": 0,
"drive_files": {},
"created_at": 1682366328,
"updated_at": 1682366328
}
],
"pagination": {
"total": 250,
"limit": 100,
"offset": 0,
"next_offset": 100,
"filter": "all"
}
}
```
```bash cURL theme={null}
curl --request GET \
--url 'https://api.tableflow.com/v2/flows/runs?status=completed&limit=50' \
--header 'Authorization: Bearer YOUR_API_KEY'
```
```python Python theme={null}
import requests
response = requests.get(
"https://api.tableflow.com/v2/flows/runs",
headers={
"Authorization": "Bearer YOUR_API_KEY"
},
params={
"status": "completed",
"limit": 50
}
)
result = response.json()
flow_runs = result["flow_runs"]
```
```javascript JavaScript theme={null}
const response = await fetch("https://api.tableflow.com/v2/flows/runs?status=completed&limit=50", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY"
}
});
const result = await response.json();
const flowRuns = result.flow_runs;
```
Array of flow run objects
The unique identifier for the flow run
The ID of the flow being executed
The workspace ID
Current status: processing, review, completed, or failed
History of status changes
Error message if the flow run failed
Custom metadata provided when running the flow
How the flow was triggered: api or manual
Unix timestamp when the flow run started
Unix timestamp when the flow run completed
Duration of the flow run in milliseconds
Google Drive files created during the flow
Unix timestamp when created
Unix timestamp when last updated
Pagination information
Total number of items
Number of items per page
Current offset
Offset for the next page (0 if no more pages)
The filter used (always "all" for this endpoint)
# Get Flow Runs by Flow
Source: https://docs.tableflow.com/api-reference/get-flow-runs-by-flow
GET /v2/flows/{id}/runs
Get a list of flow runs for a specific flow
Retrieves all flow runs for a specific flow.
## Usage Notes
* Returns all runs without pagination
* Results are ordered by creation date (newest first)
* The flow must belong to your workspace
## Request
The ID of the flow
## Response
```json theme={null}
[
{
"id": "Wp7kRnT2mX4vQ9bL",
"flow_id": "dk4g1tUg1uHLs8YU",
"workspace_id": "uT2bJNWN75YPU95r",
"status": "completed",
"status_history": [
{
"status": "processing",
"time": 1682366228,
"message": "Flow started via api"
},
{
"status": "completed",
"time": 1682366258,
"message": "Flow completed successfully"
}
],
"error": null,
"metadata": {
"customer_id": "12345",
"order_number": "PO-2024-001"
},
"trigger_method": "api",
"start_time": 1682366228,
"end_time": 1682366258,
"duration": 30000,
"drive_files": {},
"created_at": 1682366228,
"updated_at": 1682366258
},
{
"id": "hN3cYs8fKj6pA5wD",
"flow_id": "dk4g1tUg1uHLs8YU",
"workspace_id": "uT2bJNWN75YPU95r",
"status": "failed",
"status_history": [
{
"status": "processing",
"time": 1682365228,
"message": "Flow started via manual"
},
{
"status": "failed",
"time": 1682365258,
"message": "Extraction step 'Extract Invoice' failed: Template not found"
}
],
"error": "Extraction step 'Extract Invoice' failed: Template not found",
"metadata": {
"customer_id": "54321"
},
"trigger_method": "manual",
"start_time": 1682365228,
"end_time": 1682365258,
"duration": 30000,
"drive_files": {},
"created_at": 1682365228,
"updated_at": 1682365258
}
]
```
```bash cURL theme={null}
curl --request GET \
--url https://api.tableflow.com/v2/flows/dk4g1tUg1uHLs8YU/runs \
--header 'Authorization: Bearer YOUR_API_KEY'
```
```python Python theme={null}
import requests
response = requests.get(
"https://api.tableflow.com/v2/flows/dk4g1tUg1uHLs8YU/runs",
headers={
"Authorization": "Bearer YOUR_API_KEY"
}
)
flow_runs = response.json()
```
```javascript JavaScript theme={null}
const response = await fetch("https://api.tableflow.com/v2/flows/dk4g1tUg1uHLs8YU/runs", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY"
}
});
const flowRuns = await response.json();
```
Array of flow run objects
The unique identifier for the flow run
The ID of the flow being executed
The workspace ID
Current status of the flow run
* `processing` - Flow is currently executing
* `review` - Flow is paused for human review
* `completed` - Flow completed successfully
* `failed` - Flow failed (check error field)
History of status changes
The status value
Unix timestamp of the status change
Description of the status change
Error message if the flow run failed
Custom metadata provided when running the flow
How the flow was triggered: api or manual
Unix timestamp when the flow run started
Unix timestamp when the flow run completed
Duration of the flow run in milliseconds
Google Drive files created during the flow (if Google Drive integration is enabled)
Unix timestamp when the flow run was created
Unix timestamp when the flow run was last updated
# Get Flows
Source: https://docs.tableflow.com/api-reference/get-flows
GET /v2/flows
Get a list of available flows in your workspace
Retrieves all active flows in your workspace. Flows define multi-step document processing workflows that can be executed via the API.
## Usage Notes
* Only active flows are returned
* The response includes the complete flow configuration
* Use the flow ID to execute flows via the [run flow endpoint](/api-reference/run-flow)
## Request
This endpoint accepts no parameters.
## Response
```json theme={null}
[
{
"id": "dk4g1tUg1uHLs8YU",
"workspace_id": "uT2bJNWN75YPU95r",
"name": "PO to Invoice Reconciliation",
"description": "Match purchase orders with invoices and verify totals",
"file_input_config": {
"file_fields": [
{
"key": "purchase_order",
"name": "Purchase Order",
"required": true,
"file_types": ["pdf", "image"],
"max_file_size": 10485760
},
{
"key": "invoice",
"name": "Invoice",
"required": true,
"file_types": ["pdf", "image"],
"max_file_size": 10485760
}
]
},
"steps": [
{
"id": "step_1",
"title": "Extract Purchase Order",
"description": "Extract data from the purchase order",
"type": "extraction",
"order": 1,
"config": {
"template_id": "Bx9wKm4nRt7vP3cQ",
"file_key": "purchase_order"
}
},
{
"id": "step_2",
"title": "Extract Invoice",
"description": "Extract data from the invoice",
"type": "extraction",
"order": 2,
"config": {
"template_id": "Ys2hLf6jNq8dW5xA",
"file_key": "invoice"
}
},
{
"id": "step_3",
"title": "Reconcile Documents",
"description": "Match line items and verify totals",
"type": "reconciliation",
"order": 3,
"config": {
"source_step_id_1": "step_1",
"source_step_id_2": "step_2",
"table_key_1": "line_items",
"table_key_2": "line_items"
}
}
],
"active": true,
"created_at": 1682366228,
"updated_at": 1682366228
}
]
```
```bash cURL theme={null}
curl --request GET \
--url https://api.tableflow.com/v2/flows \
--header 'Authorization: Bearer YOUR_API_KEY'
```
```python Python theme={null}
import requests
response = requests.get(
"https://api.tableflow.com/v2/flows",
headers={
"Authorization": "Bearer YOUR_API_KEY"
}
)
flows = response.json()
```
```javascript JavaScript theme={null}
const response = await fetch("https://api.tableflow.com/v2/flows", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY"
}
});
const flows = await response.json();
```
Array of flow objects
The unique identifier for the flow
The workspace this flow belongs to
The name of the flow
A description of what the flow does
Configuration for file inputs
Array of file field configurations
The field key used when uploading files
Display name for the field
Whether this file is required
Allowed file types (e.g., \["pdf", "image"])
Maximum file size in bytes
Whether multiple files can be uploaded for this field
The steps that make up this flow
Unique identifier for the step
Display title for the step
Description of what the step does
Type of step: extraction, reconciliation, review, verify, etc.
Execution order of the step
Step-specific configuration
Whether the flow is active and can be run
Unix timestamp when the flow was created
Unix timestamp when the flow was last updated
# Run Flow
Source: https://docs.tableflow.com/api-reference/run-flow
POST /v2/flows/{id}/run
Execute a flow with uploaded files
Executes a flow by uploading files and triggering the configured workflow steps.
## Usage Notes
* Files are uploaded as multipart/form-data
* File field names must match the flow's configuration
* Required files must be provided or the request will fail
* The flow executes asynchronously - use the returned ID to check status
* Use metadata to include custom data that will be preserved in the flow run
## Request
The ID of the flow to run
File(s) to upload. The field name must match the `key` defined in the flow's `file_input_config.file_fields`.
For fields that accept multiple files, append an index starting at 1 (e.g., `attachments_1`, `attachments_2`).
Optional name for the flow run. This is useful for identifying flow runs in the TableFlow UI.
JSON string containing metadata for a specific file. Replace `{file_key}` with the file field key
(e.g., `purchase_order_metadata`). This metadata is associated with the individual file's extraction.
Optional extraction guidance for a specific file. Replace `{file_key}` with the file field key
(e.g., `purchase_order_guidance`). Use this to provide hints to the AI about the document structure
or specific values to look for in that particular file.
JSON string containing metadata for the entire flow run. This metadata will be included in all flow run responses and webhooks.
## Response
```json theme={null}
{
"id": "Wp7kRnT2mX4vQ9bL",
"flow_id": "dk4g1tUg1uHLs8YU",
"workspace_id": "uT2bJNWN75YPU95r",
"status": "processing",
"status_history": [
{
"status": "processing",
"time": 1682366228,
"message": "Flow started via api"
}
],
"error": null,
"metadata": {
"customer_id": "12345",
"order_number": "PO-2024-001"
},
"trigger_method": "api",
"start_time": 1682366228,
"end_time": null,
"duration": 0,
"drive_files": {},
"created_at": 1682366228,
"updated_at": 1682366228
}
```
```bash cURL theme={null}
curl --request POST \
--url https://api.tableflow.com/v2/flows/dk4g1tUg1uHLs8YU/run \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: multipart/form-data' \
--form 'purchase_order=@/path/to/po.pdf' \
--form 'invoice=@/path/to/invoice.pdf' \
--form 'name=PO-123 Reconciliation' \
--form 'purchase_order_metadata={"po_number": "PO-123"}' \
--form 'purchase_order_guidance=The PO number may include revision info like REV:0 at the end — strip that and only extract the base PO number' \
--form 'metadata={"customer_id": "12345"}'
```
```python Python theme={null}
import requests
import json
files = {
"purchase_order": open("po.pdf", "rb"),
"invoice": open("invoice.pdf", "rb")
}
data = {
"name": "PO-123 Reconciliation",
"purchase_order_metadata": json.dumps({"po_number": "PO-123"}),
"purchase_order_guidance": "The PO number may include revision info like REV:0 at the end — strip that and only extract the base PO number",
"metadata": json.dumps({"customer_id": "12345"})
}
response = requests.post(
"https://api.tableflow.com/v2/flows/dk4g1tUg1uHLs8YU/run",
headers={
"Authorization": "Bearer YOUR_API_KEY"
},
files=files,
data=data
)
flow_run = response.json()
```
```javascript JavaScript theme={null}
const formData = new FormData();
formData.append("purchase_order", purchaseOrderFile);
formData.append("invoice", invoiceFile);
formData.append("name", "PO-123 Reconciliation");
formData.append("purchase_order_metadata", JSON.stringify({ po_number: "PO-123" }));
formData.append("purchase_order_guidance", "The PO number may include revision info like REV:0 at the end — strip that and only extract the base PO number");
formData.append("metadata", JSON.stringify({ customer_id: "12345" }));
const response = await fetch("https://api.tableflow.com/v2/flows/dk4g1tUg1uHLs8YU/run", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY"
},
body: formData
});
const flowRun = await response.json();
```
The unique identifier for the flow run
The ID of the flow being executed
The workspace ID
Current status of the flow run: processing, review, completed, or failed
History of status changes
The status value
Unix timestamp of the status change
Description of the status change
Error message if the flow run failed
Custom metadata provided when running the flow
How the flow was triggered: api or manual
Unix timestamp when the flow run started
Unix timestamp when the flow run completed
Duration of the flow run in milliseconds
Unix timestamp when the flow run was created
Unix timestamp when the flow run was last updated
# Upload File for Extraction
Source: https://docs.tableflow.com/api-reference/upload-file
POST /v2/extractions/upload
Upload a file and trigger an extraction run
Uploads a file and initiates an extraction process using the specified template.
## Usage Notes
* Maximum file size: 1GB
* Files are processed according to the specified template
* Use the `metadata` parameter to include custom data (like user IDs, reference numbers) that will be preserved across all extraction API responses and webhooks
* Metadata is useful for tying back extractions to your systems, correlation, and application integration purposes
* Configure webhooks for asynchronous notifications when extractions complete
## Request
The file to upload and process. Supported formats include PDF (.pdf), Excel
(.xlsx, .xls), CSV (.csv), TSV (.tsv), and image files (.jpg, .png, .webp, .tiff).
Only one file can be uploaded per request.
The ID of the template to use for mapping the document data during extraction.
You can also pass `"auto"` and TableFlow will automatically select the best template
based on the document content and template file type settings.
Optional name for the extraction. This is useful for identifying extractions
in the TableFlow UI and can be used to label extractions in your workflow.
Optional extraction guidance to provide additional context to the AI during extraction.
Use this to give hints about the document structure, specific values to look for,
or any other information that might help improve extraction accuracy.
Optional JSON string containing custom metadata to associate with this extraction.
This can include any information you need to reference, such as user IDs, order numbers,
or other contextual data. The metadata will be included in all extraction responses
(API endpoints and webhooks), making it useful for correlating extractions with your application.
Example: `{"user_id": "123", "reference": "INV-2023-04-15", "source": "mobile-app"}`
```bash cURL theme={null}
curl -X POST https://api.tableflow.com/v2/extractions/upload \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@/path/to/your/invoice.pdf" \
-F "template_id=dk4g1tUg1uHLs8YU" \
-F "name=April 2023 Invoice" \
-F "metadata={\"user_id\":\"123\",\"reference\":\"INV-2023-04-15\"}"
```
```javascript Node.js theme={null}
const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");
async function uploadFile(filePath, templateId, options = {}) {
try {
const form = new FormData();
form.append("file", fs.createReadStream(filePath));
form.append("template_id", templateId);
if (options.name) {
form.append("name", options.name);
}
if (options.guidance) {
form.append("guidance", options.guidance);
}
if (options.metadata) {
const metadataStr = typeof options.metadata === "string"
? options.metadata
: JSON.stringify(options.metadata);
form.append("metadata", metadataStr);
}
const response = await axios.post(
"https://api.tableflow.com/v2/extractions/upload",
form,
{
headers: {
Authorization: "Bearer YOUR_API_KEY",
...form.getHeaders(),
},
}
);
console.log(response.data);
return response.data;
} catch (error) {
console.error(error);
}
}
// Example with name and metadata
uploadFile("/path/to/your/invoice.pdf", "dk4g1tUg1uHLs8YU", {
name: "April 2023 Invoice",
metadata: { user_id: "123", reference: "INV-2023-04-15", source: "web-app" },
});
```
```python Python theme={null}
import requests
import json
def upload_file(file_path, template_id, name=None, guidance=None, metadata=None):
url = "https://api.tableflow.com/v2/extractions/upload"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}
files = {
"file": open(file_path, "rb")
}
data = {
"template_id": template_id
}
if name:
data["name"] = name
if guidance:
data["guidance"] = guidance
if metadata:
if isinstance(metadata, dict):
data["metadata"] = json.dumps(metadata)
else:
data["metadata"] = metadata
response = requests.post(url, headers=headers, files=files, data=data)
return response.json()
# Example with name and metadata
extraction = upload_file(
"/path/to/your/invoice.pdf",
"dk4g1tUg1uHLs8YU",
name="April 2023 Invoice",
metadata={"user_id": "123", "reference": "INV-2023-04-15", "source": "python-client"}
)
print(extraction)
```
## Response
The unique identifier for the new extraction.
The ID of the workspace this extraction belongs to.
The ID of the template used for the extraction.
The current status of the extraction, typically "processing" for a new upload.
Additional metadata associated with the extraction.
Unix timestamp when the extraction was created.
Unix timestamp when the extraction was last updated.
```json theme={null}
{
"id": "uT2bJNWN75YPU95r",
"workspace_id": "dk4g1tUg1uHLs8YU",
"template_id": "JlLZVabDjYWzu7C9",
"status": "processing",
"metadata": {
"user_id": "123",
"reference": "INV-2023-04-15"
},
"created_at": 1682366228,
"updated_at": 1682366228
}
```
## Error Responses
Error message describing what went wrong.
```json 400 Bad Request theme={null}
{
"error": "The parameter 'template_id' is required"
}
```
```json 400 Bad Request theme={null}
{
"error": "No file was uploaded or the file is empty"
}
```
```json 400 Bad Request theme={null}
{
"error": "File type '.xyz' is not supported. Supported types are: .pdf, .xlsx, .xls, .csv, .tsv, .jpg, .png, .webp, .tiff"
}
```
```json 400 Bad Request theme={null}
{
"error": "File size 2305 MB exceeds limit of 1 GB"
}
```
```json 401 Unauthorized theme={null}
{
"error": "Invalid or missing API key"
}
```
## What Happens After Upload
After successfully uploading a file, the extraction process follows these steps:
1. **Processing** - The file is being analyzed and data is being extracted
2. **Completed** - Data extraction has finished successfully
3. **Failed** - An error occurred during extraction
You can check the status of an extraction using the [Get Extraction](/api-reference/get-extraction) endpoint:
```bash theme={null}
curl -X GET https://api.tableflow.com/v2/extractions/uT2bJNWN75YPU95r \
-H "Authorization: Bearer YOUR_API_KEY"
```
For real-time notifications when extractions complete, configure [webhooks](/webhooks) to receive events.
## File Type Support
TableFlow supports the following file types:
### PDFs
* Digital (text-based) PDFs
* Scanned (image-based) PDFs
* Multi-page documents
### Spreadsheets
* Excel files (.xlsx, .xls)
* CSV files (.csv)
* TSV files (.tsv)
* Multi-sheet workbooks
### Images
* JPEG files (.jpg)
* PNG files (.png)
* WebP files (.webp)
* TIFF files (.tiff)
# Data Types
Source: https://docs.tableflow.com/data-types
Define the expected format of extracted data
Data types define the expected format of data extracted from your documents. TableFlow supports multiple data types to ensure data is correctly formatted and validated during extraction.
Data types can be set on:
* Template fields
* Table columns
If no data type is specified, the field or column will default to the `string` type.
## Available Data Types
### String
The most flexible data type, accepting any text value.
**Accepts**: Any text value\
**Output**: The extracted value as a string
```json theme={null}
{
"name": "Customer Name",
"key": "customer_name",
"data_type": "string"
}
```
### Number
For numeric values, such as amounts, quantities, and measurements.
**Accepts**: Integers and decimal numbers of any size\
**Output**: The extracted value as a number, or null if blank\
**Validation**: Non-numeric values are flagged for review
```json theme={null}
{
"name": "Total Amount",
"key": "total_amount",
"data_type": "number"
}
```
### Date
For date and datetime values, supporting various formats.
**Accepts**: Date strings in various formats (e.g., "2023-04-15", "Apr 15, 2023", "15/04/2023")\
**Output**: The extracted value as an RFC 3339 datetime (e.g., "2023-04-15T00:00:00Z"), or null if blank\
**Validation**: Invalid date formats are flagged for review
```json theme={null}
{
"name": "Invoice Date",
"key": "invoice_date",
"data_type": "date"
}
```
### Boolean
For true/false values.
**Accepts**: "true", "t", "1", "yes", "y" for true; "false", "f", "0", "no", "n" for false (case-insensitive)\
**Output**: The extracted value as a boolean (true/false), or null if blank\
**Validation**: Non-boolean values are flagged for review
```json theme={null}
{
"name": "Is Paid",
"key": "is_paid",
"data_type": "boolean"
}
```
### Table
For defining a nested table structure within a template. This is particularly useful for complex documents that have multiple tables or nested data.
**Output**: A structured array of rows with column values
```json theme={null}
{
"name": "Line Items",
"key": "line_items",
"data_type": "table"
}
```
## How Data Types Affect Extraction
When you specify a data type:
1. **Format Guidance** - The AI uses the data type to identify the correct format when extracting
2. **Validation** - Extracted data is validated against the expected format
3. **Transformation** - Data is converted to the proper format (e.g., parsing dates)
4. **Error Flagging** - Values that don't match the expected format are flagged for review
## Data Type Examples
Here's how to define different data types in a template:
```json Template with Various Data Types theme={null}
{
"fields": [
{
"name": "Invoice Number",
"key": "invoice_number",
"data_type": "string",
"description": "The unique identifier for the invoice"
},
{
"name": "Invoice Date",
"key": "invoice_date",
"data_type": "date",
"description": "The date the invoice was issued"
},
{
"name": "Total Amount",
"key": "total_amount",
"data_type": "number",
"description": "The total amount due on the invoice"
},
{
"name": "Is Paid",
"key": "is_paid",
"data_type": "boolean",
"description": "Whether the invoice has been paid"
}
],
"tables": [
{
"name": "Line Items",
"key": "line_items",
"description": "The list of products or services on the invoice",
"columns": [
{
"name": "Description",
"key": "description",
"data_type": "string"
},
{
"name": "Quantity",
"key": "quantity",
"data_type": "number"
},
{
"name": "Unit Price",
"key": "unit_price",
"data_type": "number"
},
{
"name": "Amount",
"key": "amount",
"data_type": "number"
}
]
}
]
}
```
## Best Practices
For optimal results:
1. **Choose Appropriate Types** - Select the most specific data type that matches your expected data
2. **Add Validations** - Combine data types with [validations](/validations) for more precise data quality control
3. **Consider Format Variations** - Be aware that dates and numbers can appear in different formats in documents
4. **Test with Sample Documents** - Process representative documents to verify data type handling
## Next Steps
Learn about [validations](/validations) to ensure the quality and integrity of your extracted data.
# Extractions
Source: https://docs.tableflow.com/extractions
Process files and extract data
## What are Extractions?
Extractions are automated processes that use AI to pull structured data from your documents based on defined **[Templates](/templates)**. They analyze document content, identify relevant information, and convert unstructured documents into structured data.
## Supported Document Types
* **Spreadsheets** - Excel files (.xlsx, .xls), CSV files (.csv), TSV files (.tsv), and other tabular formats
* **PDFs** - Forms, invoices, statements, reports, and more
* **Images** - Scanned documents, receipts, business cards, and photos (.jpg, .png, .webp, .tiff)
## Create an Extraction in the Dashboard
1. Navigate to the **Extractions** page.
2. Click **New Extraction**.
3. Upload your document or provide a file URL.
4. Select an existing **[Template](/templates)** or create a new one.
5. Click **Upload** to start the process.
## Create an Extraction via API
1. **Upload a file** with the `/v2/extractions/upload` endpoint
2. **Specify a template ID** to determine how data is extracted
The API will return an extraction ID you can use to check the status and retrieve results:
```json Response theme={null}
{
"id": "ext_abcdef123456",
"template_id": "tmpl_987654321",
"file_name": "document.pdf",
"status": "processing",
"created_at": 1682366228
}
```
For more detailed API documentation, see the [API Reference](/api-reference).
## Retrieve Extraction Results
Once an Extraction has completed, you can access the data in several ways:
* **View in Dashboard** - See extracted fields and tables in the TableFlow dashboard
* **Download Results** - Export the data as JSON, CSV, or Excel files
* **API / Webhooks** - Retrieve results programmatically using the TableFlow API
## How Extractions Work
TableFlow's AI extraction process involves several key steps:
1. **Document Analysis** - AI analyzes the structure, layout, and content of your document
2. **Template Mapping** - AI matches document content to your template fields and tables
3. **Data Extraction** - AI extracts the relevant data based on context and positioning
4. **Validation** - AI validates extracted data against rules in your template
## Next Steps
After creating extractions, you can use TableFlow's [API](/api-reference) to integrate the extracted data into your applications.
```json Completed Extraction Example theme={null}
{
"id": "ext_123456789",
"template_id": "tmpl_987654321",
"status": "completed",
"confidence": 0.92, // Overall confidence score
"created_at": "2023-05-15T14:30:00Z",
"fields": {
"invoice_number": {
"value": "INV-2023-0042",
"confidence": 0.98 // Per-field confidence
},
"invoice_date": {
"value": "2023-05-10",
"confidence": 0.95
},
"due_date": {
"value": "2023-06-09",
"confidence": 0.94
},
"total_amount": {
"value": 1250.00,
"confidence": 0.97
}
},
"tables": {
"line_items": {
"rows": [
{
"description": {
"value": "Professional Services - Web Development",
"confidence": 0.96
},
"quantity": {
"value": 10,
"confidence": 0.99
},
"unit_price": {
"value": 125.00,
"confidence": 0.98
},
"amount": {
"value": 1250.00,
"confidence": 0.97
}
}
]
}
}
}
```
# Flows
Source: https://docs.tableflow.com/flows
Automate business processes
Flows allow you to automate actions based on your extracted data, creating end-to-end automation workflows that connect with your existing systems.
## What are Flows?
Flows are sequences that trigger when extractions are completed. They let you:
* **Process extracted data** immediately after extraction
* **Transform data** to meet specific requirements
* **Send data** to other systems via webhooks and APIs
* **Trigger actions** in your business processes
* **Compare and reconcile** extractions from multiple files
* **Facilitate human review** for approval or manual edits before proceeding
## Key Features
Flows trigger automatically when documents are processed, ensuring immediate
action on new data.
Apply business rules and conditions to determine how data should be
processed based on content.
Connect with external systems via webhooks, APIs, and pre-built connectors.
Format and modify extracted data to match downstream system requirements.
Enable team members to review, approve, or edit extracted data before it
continues through the workflow.
## Common Use Cases
* **ERP Integration**: Send extracted invoice data directly to your accounting system
* **CRM Updates**: Automatically create or update customer records with extracted information
* **Approval Workflows**: Route documents to different team members based on extracted content
* **Database Updates**: Insert extracted data into your database systems automatically
* **Custom API Calls**: Trigger custom business logic in your application
* **Data Reconciliation**: Compare and reconcile extractions from multiple documents against each other for validation or matching
Ready to build your own automated workflows? [Get started with Flows](/flows/getting-started) or check out our [API reference](/api-reference/flows/create) for programmatic creation.
# Introduction
Source: https://docs.tableflow.com/introduction
TableFlow is an AI document processing and automation platform that extracts structured data from PDFs, spreadsheets, and images, and streamlines complex business logic.
## Key Features
* **Data Extraction**: Extract data from PDFs, spreadsheets, and images with high accuracy
* **Intelligent Templates**: Create reusable templates for consistent data extraction
* **Data Validation**: Automatically validate extracted data against custom rules
* **Review Experience**: Intuitive UI for users to review and modify extracted data
* **Table Detection**: Identify and extract tabular data from any document
* **Developer-Friendly API**: Integrate with your existing systems and workflows
* **Multiple AI Providers**: Use the best AI model for each specific document type
## Base Extraction
Templates that tell TableFlow exactly what data to extract. Specify
fields, tables, and validation rules that match your application needs.
Upload documents and let TableFlow do the work. Our engines extract
structured data according to your template definition.
Access clean, structured data in JSON format prepared for your systems.
Receive webhooks when the data is ready.
## Core Concepts
Design extraction blueprints based on data requirements
Upload files and transform them into structured data
Build automated workflows to process your data after extraction
## Get In Touch
We'd love to hear your feedback or answer any questions! Contact us at [support@tableflow.com](mailto:support@tableflow.com).
# Slack Notifications
Source: https://docs.tableflow.com/slack-notifications
Receive notifications about extractions in Slack
TableFlow can send notifications to Slack when extractions are completed or fail. This helps your team stay informed about the status of document extractions without constantly checking the dashboard.
## Setting Up Slack Notifications
### 1. Create a Slack App
First, you'll need to create a Slack app and configure incoming webhooks:
1. Go to the [Slack API Apps page](https://api.slack.com/apps)
2. Click **Create New App**
3. Select **From scratch**
4. Enter a name for your app (e.g., "TableFlow Notifications") and select your workspace
5. Click **Create App**
### 2. Configure Incoming Webhooks
Next, you need to enable and configure incoming webhooks:
1. In your Slack app settings, click on **Incoming Webhooks** in the sidebar
2. Toggle the switch to **Activate Incoming Webhooks**
3. Click **Add New Webhook to Workspace**
4. Select the channel where you want to receive TableFlow notifications
5. Click **Allow** to give the app permission to post to the channel
6. Copy the Webhook URL that appears on the page
### 3. Configure TableFlow
Now, add the webhook URL to your TableFlow settings:
1. Navigate to your workspace settings in TableFlow
2. Select the **Webhooks** tab
3. Click **Add Endpoint**
4. Paste the Slack Webhook URL from the previous step
5. Select which events you want to receive notifications for
6. Click **Create**
## Customizing Notifications
To customize the notification format, you'll need to use transformations:
1. Navigate to the **Advanced** section of the endpoint settings
2. Toggle on the **Enabled** switch under Transformations
3. Click **Edit transformation**
4. Add your transformation code and click **Save**
Here's an example of a transformation for extraction completion notifications:
```javascript theme={null}
function handler(webhook) {
// Format different messages based on the event type
if (webhook.event === "extraction.completed") {
webhook.payload = {
text: `:white_check_mark: *Extraction Completed*
*File:* ${webhook.payload.file_name}
*Template:* ${webhook.payload.template_name}
*ID:* ${webhook.payload.extraction_id}
*Status:* Completed
*Time:* ${new Date(webhook.payload.updated_at * 1000)
.toISOString()
.replace("T", " ")
.substring(0, 19)} UTC`,
};
} else if (webhook.event === "extraction.failed") {
webhook.payload = {
text: `:x: *Extraction Failed*
*File:* ${webhook.payload.file_name}
*Template:* ${webhook.payload.template_name}
*ID:* ${webhook.payload.extraction_id}
*Status:* Failed
*Error:* ${webhook.payload.error}
*Time:* ${new Date(webhook.payload.updated_at * 1000)
.toISOString()
.replace("T", " ")
.substring(0, 19)} UTC`,
};
}
return webhook;
}
```
## Notification Types
TableFlow can send the following types of notifications to Slack:
### Extraction Completed
Sent when an extraction has been successfully completed:
```
✅ Extraction Completed
File: invoice-2023-04-15.pdf
Template: Invoice Template
ID: uT2bJNWN75YPU95r
Status: Completed
Time: 2023-04-24 14:23:48 UTC
```
### Extraction Failed
Sent when an extraction has failed:
```
❌ Extraction Failed
File: corrupted-file.pdf
Template: Invoice Template
ID: uT2bJNWN75YPU95r
Status: Failed
Error: Unable to process document: corrupt file
Time: 2023-04-24 14:23:48 UTC
```
## Filtering Notifications
For busy workspaces with many extractions, you can set up filters to only receive notifications for specific templates or file types:
Example filter to only receive notifications for PDF files:
```javascript theme={null}
function handler(webhook) {
if (webhook.payload.file_type?.key !== "document") {
webhook.cancel = true;
return webhook;
}
// Continue with formatting the notification
webhook.payload = {
text: `New ${webhook.payload.file_type.key.toUpperCase()} extraction: ${
webhook.payload.file_name
}`,
};
return webhook;
}
```
Example filter to only receive notifications for a specific template:
```javascript theme={null}
function handler(webhook) {
if (webhook.payload.template_id !== "dk4g1tUg1uHLs8YU") {
webhook.cancel = true;
return webhook;
}
// Continue with formatting the notification
webhook.payload = {
text: `New extraction using template: ${webhook.payload.template_name}`,
};
return webhook;
}
```
## Advanced Notification Formatting
You can create more advanced notifications using Slack's block kit format:
```javascript theme={null}
function handler(webhook) {
if (webhook.event === "extraction.completed") {
webhook.payload = {
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: "✅ Extraction Completed",
emoji: true,
},
},
{
type: "section",
fields: [
{
type: "mrkdwn",
text: `*File:*\n${webhook.payload.file_name}`,
},
{
type: "mrkdwn",
text: `*Template:*\n${webhook.payload.template_name}`,
},
],
},
{
type: "section",
fields: [
{
type: "mrkdwn",
text: `*Status:*\nCompleted`,
},
{
type: "mrkdwn",
text: `*Time:*\n${new Date(webhook.payload.updated_at * 1000)
.toISOString()
.replace("T", " ")
.substring(0, 19)} UTC`,
},
],
},
{
type: "actions",
elements: [
{
type: "button",
text: {
type: "plain_text",
text: "View Extraction",
emoji: true,
},
url: `https://app.tableflow.com/extractions/${webhook.payload.extraction_id}`,
},
],
},
],
};
}
return webhook;
}
```
## Troubleshooting
If you're not receiving Slack notifications:
1. **Check Permissions** - Ensure the Slack app has permission to post to the channel
2. **Verify Webhook URL** - Confirm the webhook URL is correctly entered in TableFlow
3. **Check Event Configuration** - Make sure you've enabled the events you want to receive
4. **Test Webhook** - Use the "Send Test" button in TableFlow to verify the connection
5. **Check Filters** - Ensure you haven't added filters that might be blocking all notifications
6. **Examine Logs** - Check the webhook logs in TableFlow for any errors
## Next Steps
Learn about [webhooks](/webhooks) to integrate extractions with your own systems.
# Table Detection
Source: https://docs.tableflow.com/table-detection
Automatically detect and extract tables from documents
TableFlow's table detection technology can automatically identify and extract tabular data from various document formats, including PDFs, images, and spreadsheets. This capability is essential for processing documents with complex layouts, such as invoices, financial statements, and reports.
## How Table Detection Works
TableFlow uses advanced AI algorithms to:
1. **Identify Tables** - Detect table structures within documents, even when they don't have clear borders
2. **Recognize Column Headers** - Identify and map column headers to your template
3. **Extract Cell Data** - Extract data from individual cells within the table
4. **Maintain Structure** - Preserve the relationships between rows and columns
5. **Handle Multiple Tables** - Identify and process multiple tables within a single document
## Supported Table Types
TableFlow can detect and extract data from various table formats:
### Well-Structured Tables
Tables with clear borders, consistent column spacing, and distinct headers.
### Borderless Tables
Tables without visible borders, using whitespace or alignment to define structure.
### Nested Tables
Tables within tables, common in complex financial or medical documents.
### Tables Across Multiple Pages
Tables that continue from one page to another in multi-page documents.
### Tables in Images
Tables within scanned documents or photographs.
## Table Extraction Capabilities
### Column Mapping
TableFlow automatically maps detected columns to the columns defined in your template. The AI considers:
* Column header text
* Data format
* Column position
* Context surrounding the table
### Row Identification
The system identifies individual rows within tables, maintaining data relationships even in complex layouts.
### Data Validation
After extraction, table data is validated against rules defined in your template, ensuring quality and consistency.
## Best Practices for Table Detection
To get the best results from TableFlow's table detection:
1. **Define Clear Table Structures** - Create templates with well-defined table structures
2. **Use Descriptive Column Names** - Clear column names help the AI correctly map detected columns
3. **Set Appropriate Data Types** - Define expected data types for each column
4. **Apply Validations** - Add validations to ensure the extracted data meets your requirements
5. **Test with Sample Documents** - Process representative samples to refine your template
## Example Use Cases
### Invoice Line Items
Extract product details, quantities, prices, and totals from invoice line item tables.
### Financial Statements
Extract transaction lists, account summaries, and balance details from financial documents.
### Inventory Reports
Extract product listings, quantities, and locations from inventory documents.
## Handling Table Detection Errors
If the AI encounters problems during table detection:
1. Review extraction results for accuracy
2. Adjust your template if necessary
3. Apply manual corrections to improve future extractions
4. Consider processing clearer copies of documents if quality is an issue
## Next Steps
Learn about [data types](/data-types) and how they help ensure the correct format for your extracted data.
# Templates
Source: https://docs.tableflow.com/templates
Define data requirements
## What are Templates?
Templates define what data should be extracted from your documents and how that data should be structured. They act as blueprints that guide the extraction process, ensuring consistent results across multiple documents of the same type. By defining templates once, you can process thousands of similar documents with predictable outcomes.
## Parts of a Template
* **Template Description** - Contextual information that helps AI models understand the document type and extraction purpose
* **Fields** - Individual data points to extract (e.g., invoice number, date, total amount)
* **Tables** - Structured collections of related data rows and columns (e.g., line items, transactions)
* **Table Columns** - The column definitions that determine what data to extract from each table row
Additional properties that enhance both fields and table columns:
* **[Data Types](/data-types)** - Define the format of extracted data (string, number, date, boolean, etc.)
* **[Validations](/validations)** - Rules that ensure extracted data meets your quality requirements
## Creating a Template
To create a new template:
1. Navigate to the **Templates** page.
2. Click **New Template**.
3. Provide a name and description.
4. Add **Fields**, **Tables**, and **Table Columns**.
## AI Template Mapping
TableFlow uses AI models to intelligently map data from your documents to the fields and tables in your template. For complex documents like invoices and receipts, this eliminates the need for manual field mapping.
* Analyzes document structure and content
* Identifies relevant data based on context and positioning
* Maps data to appropriate fields and tables
* Validates data against specified rules
## Template Best Practices
For optimal results with Templates:
1. **Be Specific** - Use clear, descriptive names for fields and tables
2. **Use Validations** - Implement appropriate validations to ensure data quality
3. **Test Thoroughly** - Process a variety of document samples to refine your template
4. **Iterate** - Adjust your template based on extraction results
## Next Steps
Once you've defined a template, you're ready to start creating **[Extractions](/extractions)** for file processing.
```json Template Example theme={null}
{
"name": "Invoice Template",
"description": "Template for processing invoices",
"fields": [
{
"name": "Invoice Number",
"key": "invoice_number",
"data_type": "string",
"description": "The unique identifier for the invoice"
},
{
"name": "Invoice Date",
"key": "invoice_date",
"data_type": "date",
"description": "The date the invoice was issued"
},
{
"name": "Due Date",
"key": "due_date",
"data_type": "date",
"description": "The date the invoice payment is due"
},
{
"name": "Total Amount",
"key": "total_amount",
"data_type": "number",
"description": "The total amount due on the invoice"
}
],
"tables": [
{
"name": "Line Items",
"key": "line_items",
"description": "The list of products or services on the invoice",
"columns": [
{
"name": "Description",
"key": "description",
"data_type": "string",
"description": "The description of the item"
},
{
"name": "Quantity",
"key": "quantity",
"data_type": "number",
"description": "The quantity of the item"
},
{
"name": "Unit Price",
"key": "unit_price",
"data_type": "number",
"description": "The price per unit of the item"
},
{
"name": "Amount",
"key": "amount",
"data_type": "number",
"description": "The total amount for the line item"
}
]
}
]
}
```
# Validations
Source: https://docs.tableflow.com/validations
Ensure data quality with validation rules
Validations allow you to enforce rules on extracted data to ensure quality and consistency. TableFlow supports various validation types that can be applied to both template fields and table columns.
Any data that fails validation will be flagged in the review interface, allowing for manual correction before further processing.
## How Validations Work
Validations are defined as an array on template fields or table columns:
```json theme={null}
"validations": [
{
"validate": "not_blank",
"message": "This field is required",
"severity": "error"
},
{
"validate": "regex",
"options": "^INV-\\d{4}$",
"message": "Invoice number must follow format INV-XXXX",
"severity": "error"
}
]
```
Each validation has the following properties:
* **validate** (required): The type of validation rule
* **options**: Additional configuration for the validation rule (varies by type)
* **message**: Custom error message to display on validation failure
* **severity**: The severity level of the validation failure ("error", "warn", or "info")
## Validation Types
### Universal Validations
These validations can be applied to any data type.
#### Not Blank
Ensures that the field or cell contains a non-blank value.
```json theme={null}
{
"validate": "not_blank",
"message": "This field is required"
}
```
### String Validations
These validations can only be applied to string data types.
#### List
Ensures the value matches one of the items in a predefined list. Comparisons are case-insensitive.
```json theme={null}
{
"validate": "list",
"options": ["Small", "Medium", "Large"],
"message": "Size must be one of the standard options"
}
```
#### Email
Ensures the value is a valid email address.
```json theme={null}
{
"validate": "email",
"message": "Please enter a valid email address"
}
```
#### Phone
Ensures the value is a valid phone number.
```json theme={null}
{
"validate": "phone",
"message": "Please enter a valid phone number"
}
```
#### Length
Validates the length of text content.
```json theme={null}
{
"validate": "length",
"options": {
"min": 4,
"max": 16
},
"message": "Value must be between 4 and 16 characters"
}
```
You can specify only min or max:
```json theme={null}
{
"validate": "length",
"options": {
"min": 8
},
"message": "Value must be at least 8 characters"
}
```
#### Regex
Ensures the value matches a specific regular expression pattern.
```json theme={null}
{
"validate": "regex",
"options": "^[A-Za-z0-9-]+$",
"message": "Only alphanumeric characters and hyphens are allowed"
}
```
### Number Validations
These validations can only be applied to number data types.
#### Range
Validates that the number falls within a specific range.
```json theme={null}
{
"validate": "range",
"options": {
"min": 0,
"max": 100
},
"message": "Value must be between 0 and 100"
}
```
You can specify only min or max:
```json theme={null}
{
"validate": "range",
"options": {
"min": 0
},
"message": "Value must be greater than or equal to 0"
}
```
#### Decimal
Validates the number of decimal places.
```json theme={null}
{
"validate": "decimal",
"options": {
"places": 2
},
"message": "Value must have exactly 2 decimal places"
}
```
### Date Validations
These validations can only be applied to date data types.
#### Date Range
Validates that a date falls within a specific range.
```json theme={null}
{
"validate": "date_range",
"options": {
"min": "2023-01-01",
"max": "2023-12-31"
},
"message": "Date must be in 2023"
}
```
## Validation Severity Levels
TableFlow supports three severity levels for validations:
* **error**: Prevents extraction data from being used until fixed
* **warning**: Allows data to be used but indicates potential issues
* **info**: Provides informational feedback without blocking
```json theme={null}
{
"validate": "not_blank",
"message": "This field is required",
"severity": "error"
}
```
## Combining Multiple Validations
You can apply multiple validation rules to the same field or column. All validations must pass for the data to be considered valid.
```json theme={null}
"validations": [
{
"validate": "not_blank",
"message": "This field is required"
},
{
"validate": "regex",
"options": "^[A-Z]\\d{5}$",
"message": "Product code must start with a capital letter followed by 5 digits"
}
]
```
## How Validations Affect Extraction
During the document extraction process:
1. Data is extracted from the document based on the template
2. Each extracted value is checked against applicable validations
3. Values that fail validation are flagged for review
4. The review interface highlights validation errors with their messages
5. Users can correct the data before finalizing the extraction
## Example Validation Scenarios
### Invoice Number Validation
```json theme={null}
{
"name": "Invoice Number",
"key": "invoice_number",
"data_type": "string",
"validations": [
{
"validate": "not_blank",
"message": "Invoice number is required"
},
{
"validate": "regex",
"options": "^INV-\\d{4}$",
"message": "Invoice number must follow format INV-XXXX"
}
]
}
```
### Amount Validation
```json theme={null}
{
"name": "Total Amount",
"key": "total_amount",
"data_type": "number",
"validations": [
{
"validate": "not_blank",
"message": "Total amount is required"
},
{
"validate": "range",
"options": {
"min": 0
},
"message": "Total amount must be positive"
},
{
"validate": "decimal",
"options": {
"places": 2
},
"message": "Total amount must have exactly 2 decimal places"
}
]
}
```
## Best Practices
For optimal validation results:
1. **Start Simple** - Begin with basic validations and add complexity as needed
2. **Use Clear Messages** - Write clear, descriptive validation messages
3. **Combine Validations** - Use multiple validation types for complex rules
4. **Set Appropriate Severity** - Use error for critical validations, warnings for less critical issues
5. **Test Thoroughly** - Verify validations work with real-world documents
## Next Steps
Learn how to use [webhooks](/webhooks) to integrate extracted data with your application.
# Webhooks
Source: https://docs.tableflow.com/webhooks
Integrate document extraction with your systems in real-time
TableFlow uses webhooks to push real-time notifications when document extractions are completed or updated. This allows your systems to automatically process extraction results without polling the API.
## How Webhooks Work
Here's how the extraction webhook flow works:
1. A document is uploaded and processed by TableFlow
2. TableFlow extracts data according to your template
3. When processing completes, TableFlow sends a webhook notification to your endpoint
4. Your system receives the webhook with extraction details
5. You can then retrieve the full extraction data using the [API](/api-reference/get-extraction)
Webhooks contain metadata about the extraction. To retrieve the full
extraction data including extracted fields and tables, use the API with the
extraction ID from the webhook.
## Configuring Webhooks
### 1. Create an Endpoint
First, create an endpoint in your application that can receive HTTP POST requests. This endpoint will receive the webhook payloads from TableFlow.
For testing, you can use [Svix Play](https://play.svix.com/) to quickly set up a temporary webhook endpoint.
### 2. Add the Endpoint to TableFlow
Navigate to your workspace settings in the TableFlow dashboard. Under the "Webhooks" section, add your endpoint URL and select the events you want to receive:
### 3. Send a Test Event
You can send a test event to verify your webhook setup:
You'll be able to see the webhook receipt in your logs and in your endpoint system:
## Webhook Events
TableFlow supports the following webhook events:
### extraction.completed
Sent when extraction processing has completed successfully.
```json theme={null}
{
"event": "extraction.completed",
"data": {
"extraction_id": "uT2bJNWN75YPU95r",
"template_id": "dk4g1tUg1uHLs8YU",
"template_name": "Invoice Template",
"file_name": "invoice-2023-04-15.pdf",
"file_type": {
"key": "document",
"extension": "pdf",
"mime_type": "application/pdf"
},
"status": "completed",
"created_at": 1682366228,
"updated_at": 1682366240,
"metadata": {
"field_count": 6,
"table_count": 1,
"valid_percentage": 95
}
}
}
```
### extraction.failed
Sent when extraction processing has failed.
```json theme={null}
{
"event": "extraction.failed",
"data": {
"extraction_id": "uT2bJNWN75YPU95r",
"template_id": "dk4g1tUg1uHLs8YU",
"file_name": "invoice-2023-04-15.pdf",
"file_type": {
"key": "document",
"extension": "pdf",
"mime_type": "application/pdf"
},
"status": "failed",
"error": "Unable to process document: corrupt file",
"created_at": 1682366228,
"updated_at": 1682366235
}
}
```
## Webhook Security
TableFlow signs all webhook requests with a signature in the `svix-signature` header. You can use this signature to verify that the webhook is genuinely from TableFlow.
```javascript theme={null}
// Example signature verification in Node.js
const crypto = require("crypto");
function verifyWebhook(payload, headers, secret) {
const signature = headers["svix-signature"];
if (!signature) return false;
const hmac = crypto.createHmac("sha256", secret);
const digest = hmac.update(payload).digest("hex");
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}
```
## Transforming and Filtering Webhooks
You can transform webhook payloads or filter webhooks based on their content before they're sent to your endpoint.
### Enabling Transformations
To add a transformation, select "Enable" and "Edit transformation" under the "Advanced" tab of an endpoint:
### Transform
You can modify the webhook payload to match your system's requirements:
```javascript theme={null}
function handler(webhook) {
// Add custom properties
webhook.payload.customProperty = "Custom Value";
// Transform existing properties
if (webhook.payload.file_type?.key === "document") {
webhook.payload.documentType = "Document";
} else if (webhook.payload.file_type?.key === "spreadsheet") {
webhook.payload.documentType = "Spreadsheet";
}
return webhook;
}
```
### Filter
You can filter webhooks based on their content to only receive specific notifications:
```javascript theme={null}
function handler(webhook) {
// Only receive webhooks for PDF files
if (webhook.payload.file_type?.key !== "document") {
webhook.cancel = true;
}
// Only receive webhooks for specific templates
if (webhook.payload.template_id !== "dk4g1tUg1uHLs8YU") {
webhook.cancel = true;
}
return webhook;
}
```
## Webhook Retries
If your endpoint returns a non-2xx status code, TableFlow will automatically retry the webhook delivery with exponential backoff:
* First retry: 5 minutes after the initial attempt
* Second retry: 30 minutes after the first retry
* Third retry: 2 hours after the second retry
* Fourth retry: 5 hours after the third retry
* Fifth retry: 10 hours after the fourth retry
After five failed attempts, the webhook will be marked as failed and will not be retried again.
## Best Practices
1. **Respond Quickly** - Your webhook endpoint should respond with a 2xx status code as quickly as possible
2. **Process Asynchronously** - Handle the webhook processing in a background job or queue
3. **Verify Signatures** - Always verify webhook signatures to ensure security
4. **Handle Duplicates** - Design your webhook handler to be idempotent to handle potential duplicate deliveries
5. **Monitor Logs** - Regularly check your webhook logs to identify and resolve any delivery issues
## Next Steps
Learn how to set up [Slack notifications](/slack-notifications) to monitor your extractions in real-time.