curl --location --request POST 'https://api-prod.extend.app/workflow_runs/batch' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_TOKEN>' \
--data '{
"workflowId": "workflow_abc789",
"version": "2",
"inputs": [
{
"file": {
"fileName": "invoice_1.pdf",
"fileUrl": "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
"metadata": {
"customer_id": "cust_123",
"source": "batch_upload"
}
},
{
"file": {
"fileId": "file_def456"
},
"metadata": {
"customer_id": "cust_456",
"source": "batch_upload"
}
},
{
"rawText": "This is the raw text content for the third run.",
"metadata": {
"internal_ref": "ref_789"
}
}
]
}'
async function runWorkflowBatch() {
const apiToken = "<API_TOKEN>";
const url = "https://api-prod.extend.app/workflow_runs/batch";
const payload = {
workflowId: "workflow_abc789",
version: "2",
inputs: [
{
file: {
fileName: "invoice_1.pdf",
fileUrl: "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
name: "Run for Invoice 1",
metadata: {
customer_id: "cust_123",
source": "batch_upload"
}
},
{
file: {
fileId: "file_def456"
},
name: "Run for Existing File DEF456",
metadata: {
customer_id": "cust_456",
source": "batch_upload"
}
},
{
rawText: "This is the raw text content for the third run.",
name: "Run for Raw Text Input",
metadata: {
internal_ref": "ref_789"
}
}
]
};
try {
const response = await fetch(url, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const data = await response.json();
if (!response.ok) {
console.error(`Error: ${response.status}`, data);
// Log the response text for more detailed debugging if needed
// console.error("Response text:", await response.text());
return;
}
console.log("Success:", data);
} catch (error) {
console.error("Request failed:", error);
}
}
runWorkflowBatch();
import requests
import json
api_token = "<API_TOKEN>"
url = "https://api-prod.extend.app/workflow_runs/batch"
payload = {
"workflowId": "workflow_abc789",
"version": "2",
"inputs": [
{
"file": {
"fileName": "invoice_1.pdf",
"fileUrl": "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
"metadata": {
"customer_id": "cust_123",
"source": "batch_upload"
}
},
{
"file": {
"fileId": "file_def456"
},
"metadata": {
"customer_id": "cust_456",
"source": "batch_upload"
}
},
{
"rawText": "This is the raw text content for the third run.",
"metadata": {
"internal_ref": "ref_789"
}
}
]
}
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.status_code)
print(response.json())
{
"success": true,
"batchId": "batch_zyx987"
}
Workflow Endpoints
Batch Run Workflow
Submit a batch of files to run through a specified workflow.
curl --location --request POST 'https://api-prod.extend.app/workflow_runs/batch' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_TOKEN>' \
--data '{
"workflowId": "workflow_abc789",
"version": "2",
"inputs": [
{
"file": {
"fileName": "invoice_1.pdf",
"fileUrl": "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
"metadata": {
"customer_id": "cust_123",
"source": "batch_upload"
}
},
{
"file": {
"fileId": "file_def456"
},
"metadata": {
"customer_id": "cust_456",
"source": "batch_upload"
}
},
{
"rawText": "This is the raw text content for the third run.",
"metadata": {
"internal_ref": "ref_789"
}
}
]
}'
async function runWorkflowBatch() {
const apiToken = "<API_TOKEN>";
const url = "https://api-prod.extend.app/workflow_runs/batch";
const payload = {
workflowId: "workflow_abc789",
version: "2",
inputs: [
{
file: {
fileName: "invoice_1.pdf",
fileUrl: "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
name: "Run for Invoice 1",
metadata: {
customer_id: "cust_123",
source": "batch_upload"
}
},
{
file: {
fileId: "file_def456"
},
name: "Run for Existing File DEF456",
metadata: {
customer_id": "cust_456",
source": "batch_upload"
}
},
{
rawText: "This is the raw text content for the third run.",
name: "Run for Raw Text Input",
metadata: {
internal_ref": "ref_789"
}
}
]
};
try {
const response = await fetch(url, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const data = await response.json();
if (!response.ok) {
console.error(`Error: ${response.status}`, data);
// Log the response text for more detailed debugging if needed
// console.error("Response text:", await response.text());
return;
}
console.log("Success:", data);
} catch (error) {
console.error("Request failed:", error);
}
}
runWorkflowBatch();
import requests
import json
api_token = "<API_TOKEN>"
url = "https://api-prod.extend.app/workflow_runs/batch"
payload = {
"workflowId": "workflow_abc789",
"version": "2",
"inputs": [
{
"file": {
"fileName": "invoice_1.pdf",
"fileUrl": "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
"metadata": {
"customer_id": "cust_123",
"source": "batch_upload"
}
},
{
"file": {
"fileId": "file_def456"
},
"metadata": {
"customer_id": "cust_456",
"source": "batch_upload"
}
},
{
"rawText": "This is the raw text content for the third run.",
"metadata": {
"internal_ref": "ref_789"
}
}
]
}
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.status_code)
print(response.json())
{
"success": true,
"batchId": "batch_zyx987"
}
This endpoint allows you to efficiently initiate large batches of workflow runs in a single request (up to 1,000 in a single request, but you can queue up multiple batches in rapid succession). It accepts an array of inputs, each containing a file and metadata pair. The primary use case for this endpoint is for doing large bulk runs of >1000 files at a time that can process over the course of a few hours without needing to manage rate limits that would likely occur using the primary run endpoint.
Unlike the single Run Workflow endpoint which returns the details of the created workflow runs immediately, this batch endpoint returns a
batchId.
Our recommended usage pattern is to integrate with Webhooks for consuming results, using the metadata and batchId to match up results to the original inputs in your downstream systems. However, you can integrate in a polling mechanism by using a combination of the List Workflow Runs endpoint to fetch all runs via a batch, and then Get Workflow Run to fetch the full outputs each run.
Body
string
required
The ID of the workflow that the inputs will be run through. This ID can be found
by viewing the workflow on the Extend platform.
string
An optional version of the workflow to use. This can be a specific version number (e.g.,
"1", "2") found on the Extend platform, or "draft" to use the current unpublished draft version.
When a version is not supplied, the latest deployed version of the workflow will be used.Input[]
required
An array of input objects to be processed by the workflow. Each object represents a single workflow run to be created.
The array must contain at least 1 input and at most 1000 inputs.
Show Properties
Show Properties
object
Specifies a file to be processed. Either
file or rawText must be provided for each input.Show File Object Properties
Show File Object Properties
string
A presigned URL for the file. For the batch endpoint, we suggest a slightly longer expiration time, ideally 30 minutes for a worst case scenario.
string
An existing Extend file ID (e.g., from a previous workflow run or file upload). If provided, Extend will reuse the existing file data. Either
fileUrl or fileId must be provided if the file object is used.string
The name to associate with the file. If not provided when using
fileUrl, the name may be inferred from the URL. This param is only for your reference, and will be rendered in our dashboard, it is not used by the workflow.string
A string containing raw text data to be processed. This will be treated as a
.txt file by the workflow. Use the file parameter for structured data or specific file types. Either file or rawText must be provided for each input.object
An optional object containing arbitrary key-value pairs to associate with this specific workflow run. This metadata will be included in webhook payloads and responses when fetching the workflow run details.
object
An optional object containing secrets to be used by processors within the workflow for this specific run. Secrets provided here override any globally configured secrets for the workflow.
Response
boolean
Indicates whether the batch request was successfully accepted and queued.
true signifies success.string
A unique identifier for the submitted batch. This ID can be used to correlate the workflow runs created by this request. You can find this
batchId associated with individual runs when listing workflow runs or in webhook payloads.Processing and Monitoring
Upon successful submission, the endpoint returns abatchId. The individual workflow runs are then queued for processing.
- Monitoring: Track the progress and consume results of individual runs using Webhooks. Subscribe to events like
workflow_run.completed,workflow_run.failed, etc. The webhook payload for these events will include the correspondingbatchIdand themetadatayou provided for each input. - Fetching Results: You can also use the List Workflow Runs endpoint and filter using the
batchIdquery param.
curl --location --request POST 'https://api-prod.extend.app/workflow_runs/batch' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_TOKEN>' \
--data '{
"workflowId": "workflow_abc789",
"version": "2",
"inputs": [
{
"file": {
"fileName": "invoice_1.pdf",
"fileUrl": "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
"metadata": {
"customer_id": "cust_123",
"source": "batch_upload"
}
},
{
"file": {
"fileId": "file_def456"
},
"metadata": {
"customer_id": "cust_456",
"source": "batch_upload"
}
},
{
"rawText": "This is the raw text content for the third run.",
"metadata": {
"internal_ref": "ref_789"
}
}
]
}'
async function runWorkflowBatch() {
const apiToken = "<API_TOKEN>";
const url = "https://api-prod.extend.app/workflow_runs/batch";
const payload = {
workflowId: "workflow_abc789",
version: "2",
inputs: [
{
file: {
fileName: "invoice_1.pdf",
fileUrl: "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
name: "Run for Invoice 1",
metadata: {
customer_id: "cust_123",
source": "batch_upload"
}
},
{
file: {
fileId: "file_def456"
},
name: "Run for Existing File DEF456",
metadata: {
customer_id": "cust_456",
source": "batch_upload"
}
},
{
rawText: "This is the raw text content for the third run.",
name: "Run for Raw Text Input",
metadata: {
internal_ref": "ref_789"
}
}
]
};
try {
const response = await fetch(url, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const data = await response.json();
if (!response.ok) {
console.error(`Error: ${response.status}`, data);
// Log the response text for more detailed debugging if needed
// console.error("Response text:", await response.text());
return;
}
console.log("Success:", data);
} catch (error) {
console.error("Request failed:", error);
}
}
runWorkflowBatch();
import requests
import json
api_token = "<API_TOKEN>"
url = "https://api-prod.extend.app/workflow_runs/batch"
payload = {
"workflowId": "workflow_abc789",
"version": "2",
"inputs": [
{
"file": {
"fileName": "invoice_1.pdf",
"fileUrl": "https://your-presigned-url.s3.amazonaws.com/invoice_1.pdf?..."
},
"metadata": {
"customer_id": "cust_123",
"source": "batch_upload"
}
},
{
"file": {
"fileId": "file_def456"
},
"metadata": {
"customer_id": "cust_456",
"source": "batch_upload"
}
},
{
"rawText": "This is the raw text content for the third run.",
"metadata": {
"internal_ref": "ref_789"
}
}
]
}
headers = {
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.status_code)
print(response.json())
{
"success": true,
"batchId": "batch_zyx987"
}
Error Responses
Common errors include:- 400 Bad Request: Invalid request body (e.g., missing required fields, array size limits exceeded, issues with
fileUrlorfileId). The response body will contain anerrormessage detailing the specific validation issues. Can also indicate issues accessing a providedfileUrl. - 401 Unauthorized: Missing or invalid API token.
- 403 Forbidden: The API token does not have permission to access the specified workflow.
- 404 Not Found: The specified
workflowIdorversiondoes not exist. - 429 Too Many Requests: The request was rate limited. Please try again later.
- 500 Internal Server Error: An unexpected error occurred on the server.
{
"success": false,
"error": "Validation Error: Array must contain at most 1000 element(s): param: inputs"
}
{
"success": false,
"error": "Resource not found."
}

