Skip to main content
POST
/
v3
/
workflows
/
{workflow_id}
/
upload
/
run
/
curl -X POST 'https://api.anyformat.ai/v3/workflows/0686bb97-8c30-70f0-8000-97669e000eb8/upload/run/' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Idempotency-Key: 7c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f' \
  -F 'files=@/path/to/invoice.pdf'
import requests
import time

workflow_id = "0686bb97-8c30-70f0-8000-97669e000eb8"
base = "https://api.anyformat.ai"
headers = {"Authorization": "Bearer YOUR_API_KEY"}

with open("invoice.pdf", "rb") as f:
    triggered = requests.post(
        f"{base}/v3/workflows/{workflow_id}/upload/run/",
        headers={**headers, "Idempotency-Key": "7c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f"},
        files=[("files", f)],
    ).json()

run_url = f"{base}/v3/runs/{triggered['run_id']}/"
for _ in range(100):
    run = requests.get(run_url, headers=headers).json()
    if run["status"] == "processed":
        print(run["results"])
        break
    if run["status"] in ("error", "cancelled"):
        print(f"Terminal: {run['status']}")
        break
    time.sleep(3)
interface RunTriggered {
  run_id: string;
  document_packet_id: string;
  workflow_id: string;
  status: 'queued' | 'in_progress' | 'processed' | 'error' | 'cancelled';
}

const workflowId = '0686bb97-8c30-70f0-8000-97669e000eb8';
const formData = new FormData();
formData.append('files', fileInput.files[0]);

const response = await fetch(
  `https://api.anyformat.ai/v3/workflows/${workflowId}/upload/run/`,
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Idempotency-Key': crypto.randomUUID(),
    },
    body: formData,
  }
);

if (!response.ok) {
  throw new Error(`API error: ${response.status}`);
}

const triggered: RunTriggered = await response.json();
console.log(triggered.run_id);
{
  "run_id": "069dcc2c-e14c-7606-8000-2ee4fb17b4f9",
  "document_packet_id": "069dcc2c-e14c-7606-8000-2ee4fb17b4e1",
  "workflow_id": "0686bb97-8c30-70f0-8000-97669e000eb8",
  "status": "queued"
}
Rate limit tier: submission (60 req/min) — see Rate limits. Uploads 1–10 files as a single document packet and immediately enqueues a run on the workflow’s latest version — the one-shot composition of Upload and Run packet. This is the shortest path from bytes to structured data. The 202 response returns the new run_id. Poll GET /v3/runs/{run_id}/ until status is terminal — the results arrive inline on that same read. For production integrations, prefer webhooks over polling. Send the files as multipart form data under the files field (repeat it for a multi-file packet); files above the per-file size cap are rejected at slot mint (before any bytes reach S3). Packet creation is all-or-nothing.
Retries are safe with Idempotency-Key. Retrying with the same key replays the original packet and run — no duplicate upload, no second extraction billed. See Idempotency.
An organization without extraction credit receives 402 PAYMENT_REQUIRED.
curl -X POST 'https://api.anyformat.ai/v3/workflows/0686bb97-8c30-70f0-8000-97669e000eb8/upload/run/' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Idempotency-Key: 7c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f' \
  -F 'files=@/path/to/invoice.pdf'
import requests
import time

workflow_id = "0686bb97-8c30-70f0-8000-97669e000eb8"
base = "https://api.anyformat.ai"
headers = {"Authorization": "Bearer YOUR_API_KEY"}

with open("invoice.pdf", "rb") as f:
    triggered = requests.post(
        f"{base}/v3/workflows/{workflow_id}/upload/run/",
        headers={**headers, "Idempotency-Key": "7c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f"},
        files=[("files", f)],
    ).json()

run_url = f"{base}/v3/runs/{triggered['run_id']}/"
for _ in range(100):
    run = requests.get(run_url, headers=headers).json()
    if run["status"] == "processed":
        print(run["results"])
        break
    if run["status"] in ("error", "cancelled"):
        print(f"Terminal: {run['status']}")
        break
    time.sleep(3)
interface RunTriggered {
  run_id: string;
  document_packet_id: string;
  workflow_id: string;
  status: 'queued' | 'in_progress' | 'processed' | 'error' | 'cancelled';
}

const workflowId = '0686bb97-8c30-70f0-8000-97669e000eb8';
const formData = new FormData();
formData.append('files', fileInput.files[0]);

const response = await fetch(
  `https://api.anyformat.ai/v3/workflows/${workflowId}/upload/run/`,
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Idempotency-Key': crypto.randomUUID(),
    },
    body: formData,
  }
);

if (!response.ok) {
  throw new Error(`API error: ${response.status}`);
}

const triggered: RunTriggered = await response.json();
console.log(triggered.run_id);
{
  "run_id": "069dcc2c-e14c-7606-8000-2ee4fb17b4f9",
  "document_packet_id": "069dcc2c-e14c-7606-8000-2ee4fb17b4e1",
  "workflow_id": "0686bb97-8c30-70f0-8000-97669e000eb8",
  "status": "queued"
}

Authorizations

Authorization
string
header
required

API key issued from app.anyformat.ai/api-key. Send as Authorization: Bearer <key>.

Headers

Idempotency-Key
string | null

Optional caller-supplied key (Stripe convention). Retrying the request with the same key replays the original packet AND run — no duplicate upload, no second extraction.

Path Parameters

workflow_id
string
required

Body

multipart/form-data
files
string[]
required

1..10 files forming one document packet.

Response

Successful Response

202 response for both run triggers (upload/run/ and document-packets/{id}/run/).

run_id
string
required

Unique identifier of the new run (hyphenated UUID).

Example:

"069dcc2c-e14c-7606-8000-2ee4fb17b4f9"

document_packet_id
string
required

The document packet the run executes on (hyphenated UUID).

Example:

"069dcc2c-e14c-7606-8000-2ee4fb17b4e1"

workflow_id
string
required

The workflow being run (hyphenated UUID).

Example:

"0686bb97-8c30-70f0-8000-97669e000eb8"

status
enum<string>
required

Status at acceptance time — normally queued.

Available options:
queued,
in_progress,
processed,
error,
cancelled
Example:

"queued"