# 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** Create Slack 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** Configure Slack App 4. Select the channel where you want to receive TableFlow notifications 5. Click **Allow** to give the app permission to post to the channel Select Slack Channel 6. Copy the Webhook URL that appears on the page Copy Webhook URL ### 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** TableFlow Webhook Settings ## 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** Enable Transformations 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. Svix Play ### 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: Add Endpoint ### 3. Send a Test Event You can send a test event to verify your webhook setup: Testing You'll be able to see the webhook receipt in your logs and in your endpoint system: Logs ## 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: Transformations ### Transform You can modify the webhook payload to match your system's requirements: Transform Example ```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: Filter Example ```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.