Skip to content

Batch Operations

Submit and manage batch translation jobs for files and structured data.


POST /v1/jobs/batch-file

Upload multiple files for translation in a single request. Each file becomes a separate job grouped under a shared batch_id.

Authentication

Header: X-API-Key: your_api_key

Content-Type: multipart/form-data Status: 202 Accepted

Form Fields

Field Type Required Default Description
files file[] yes -- One or more files to translate.
source_lang string yes -- BCP-47 source language code.
target_lang string yes -- BCP-47 target language code.
briefing_json string (JSON) no null JSON-encoded translation options (shared across all files).

Response (202)

{
  "batch_id": "batch_550e8400-...",
  "job_ids": [
    "550e8400-e29b-41d4-a716-446655440001",
    "550e8400-e29b-41d4-a716-446655440002",
    "550e8400-e29b-41d4-a716-446655440003"
  ],
  "total_jobs": 3,
  "status": "queued"
}

Examples

curl -X POST https://app.falara.io/v1/jobs/batch-file \
  -H "X-API-Key: $FALARA_API_KEY" \
  -F "files=@brochure_de.docx" \
  -F "files=@datasheet_de.xlsx" \
  -F "files=@manual_de.pdf" \
  -F "source_lang=de" \
  -F "target_lang=en" \
  -F 'briefing_json={"domain":"technical","project_name":"Product Launch"}'
import requests

files = [
    ("files", ("brochure_de.docx", open("brochure_de.docx", "rb"))),
    ("files", ("datasheet_de.xlsx", open("datasheet_de.xlsx", "rb"))),
    ("files", ("manual_de.pdf", open("manual_de.pdf", "rb"))),
]

response = requests.post(
    "https://app.falara.io/v1/jobs/batch-file",
    headers={"X-API-Key": FALARA_API_KEY},
    files=files,
    data={
        "source_lang": "de",
        "target_lang": "en",
        "briefing_json": '{"domain":"technical","project_name":"Product Launch"}',
    },
)
print(response.json())
const formData = new FormData();
formData.append("files", brochureBlob, "brochure_de.docx");
formData.append("files", datasheetBlob, "datasheet_de.xlsx");
formData.append("files", manualBlob, "manual_de.pdf");
formData.append("source_lang", "de");
formData.append("target_lang", "en");
formData.append(
  "briefing_json",
  JSON.stringify({ domain: "technical", project_name: "Product Launch" })
);

const response = await fetch("https://app.falara.io/v1/jobs/batch-file", {
  method: "POST",
  headers: { "X-API-Key": FALARA_API_KEY },
  body: formData,
});
const data = await response.json();
console.log(data);

Errors

Status Description
401 Invalid or missing API key.
422 Validation error (unsupported format, missing fields).
429 Rate limit or word quota exceeded.

GET /v1/jobs/batch/{batch_id}

Get the aggregated status of all jobs in a batch.

Authentication

Header: X-API-Key: your_api_key

Status: 200 OK

Query Parameters

Parameter Type Required Default Description
limit int no 20 Number of jobs to return per page.
cursor string no null Pagination cursor from a previous response.

Response

{
  "batch_id": "b1c2d3e4-...",
  "status": "processing",
  "source_language": "de",
  "target_languages": ["en", "fr"],
  "completed": 1,
  "total": 4,
  "total_cost_eur": 0.14,
  "data": [
    {
      "job_id": "550e8400-...",
      "filename": "brochure.docx",
      "status": "completed",
      "target_language": "en",
      "qa_score": 94.5
    }
  ],
  "pagination": {
    "cursor": "eyJ...",
    "has_more": true
  }
}

Batch Status Values

Status Description
processing At least one job is still running.
completed All jobs reached completed or completed_with_blocks.
partial All jobs are terminal, but some failed or need review.

Examples

curl -X GET "https://app.falara.io/v1/jobs/batch/b1c2d3e4-...?limit=10" \
  -H "X-API-Key: $FALARA_API_KEY"
import requests

response = requests.get(
    f"https://app.falara.io/v1/jobs/batch/{batch_id}",
    headers={"X-API-Key": FALARA_API_KEY},
    params={"limit": 10},
)
batch = response.json()
print(f"Status: {batch['status']} ({batch['completed']}/{batch['total']})")
const response = await fetch(
  `https://app.falara.io/v1/jobs/batch/${batchId}?limit=10`,
  { headers: { "X-API-Key": FALARA_API_KEY } }
);
const batch = await response.json();
console.log(`Status: ${batch.status} (${batch.completed}/${batch.total})`);

Errors

Status Description
401 Invalid or missing API key.
404 Batch not found.

GET /v1/jobs/batch/{batch_id}/download

Download all completed translations from a batch as a ZIP archive.

Authentication

Header: X-API-Key: your_api_key

Status: 200 OK Content-Type: application/zip

Query Parameters

Parameter Type Required Default Description
structure "folders" | "suffix" no "folders" ZIP layout for multi-language batches.

ZIP Layouts

folders (default): Files organized by target language in subdirectories.

batch_b1c2.zip
├── manifest.json
├── en/
│   └── translated_brochure.docx
└── fr/
    └── translated_brochure.docx

suffix: Files placed flat with a language suffix appended to the filename.

batch_b1c2.zip
├── manifest.json
├── translated_brochure_en.docx
└── translated_brochure_fr.docx

Every ZIP includes a manifest.json with job metadata.

Partial Batches

If some jobs in the batch are still processing, only completed files are included. The response header X-Falara-Batch-Complete indicates whether all jobs are done (true / false).

Examples

curl -X GET "https://app.falara.io/v1/jobs/batch/batch_550e8400-.../download?structure=folders" \
  -H "X-API-Key: $FALARA_API_KEY" \
  -o translations.zip
import requests

response = requests.get(
    f"https://app.falara.io/v1/jobs/batch/{batch_id}/download",
    headers={"X-API-Key": FALARA_API_KEY},
    params={"structure": "folders"},
)

with open("translations.zip", "wb") as f:
    f.write(response.content)

batch_complete = response.headers.get("X-Falara-Batch-Complete")
print(f"All jobs complete: {batch_complete}")
const response = await fetch(
  `https://app.falara.io/v1/jobs/batch/${batchId}/download?structure=folders`,
  { headers: { "X-API-Key": FALARA_API_KEY } }
);

const blob = await response.blob();
const batchComplete = response.headers.get("X-Falara-Batch-Complete");
console.log(`All jobs complete: ${batchComplete}`);

Errors

Status Description
401 Invalid or missing API key.
404 Batch not found.
409 No completed file jobs in this batch yet.

POST /v1/jobs/batch-csv

Submit a CSV file for batch processing using a Structure Template (Creation Mode).

Authentication

Header: X-API-Key: your_api_key

Content-Type: multipart/form-data Status: 202 Accepted (or 200 OK with dry_run=true)

Form Fields

Field Type Required Default Description
file file yes -- CSV file (UTF-8 encoded).
structure_template_id string yes -- Template ID or slug defining the output structure.
source_lang string yes -- BCP-47 source language code.
target_lang string yes -- BCP-47 target language code.
mapping_id string no null CSV column mapping ID. If omitted, columns are auto-detected.

Query Parameters

Parameter Type Required Default Description
dry_run boolean no false Set to true to preview without creating jobs.

Response (202 -- Creation)

{
  "batch_id": "batch_550e8400-...",
  "total_rows": 50,
  "jobs_created": 50,
  "job_ids": [
    "550e8400-e29b-41d4-a716-446655440001",
    "550e8400-e29b-41d4-a716-446655440002"
  ]
}

Response (200 -- Dry Run)

{
  "total_rows": 50,
  "sample_products": [
    {
      "row": 1,
      "source_fields": {
        "title": "Ergonomischer Bürostuhl",
        "description": "Höhenverstellbar mit Lendenwirbelstütze."
      }
    }
  ],
  "template_fields": [
    { "field": "title", "max_length": 150, "required": true },
    { "field": "description", "max_length": 5000, "required": true }
  ]
}

Examples

# Dry run (preview)
curl -X POST "https://app.falara.io/v1/jobs/batch-csv?dry_run=true" \
  -H "X-API-Key: $FALARA_API_KEY" \
  -F "file=@products.csv" \
  -F "structure_template_id=amazon-listing" \
  -F "source_lang=de" \
  -F "target_lang=en"

# Create jobs
curl -X POST https://app.falara.io/v1/jobs/batch-csv \
  -H "X-API-Key: $FALARA_API_KEY" \
  -F "file=@products.csv" \
  -F "structure_template_id=amazon-listing" \
  -F "source_lang=de" \
  -F "target_lang=en" \
  -F "mapping_id=map_abc123"
import requests

# Dry run
with open("products.csv", "rb") as f:
    response = requests.post(
        "https://app.falara.io/v1/jobs/batch-csv",
        params={"dry_run": "true"},
        headers={"X-API-Key": FALARA_API_KEY},
        files={"file": ("products.csv", f)},
        data={
            "structure_template_id": "amazon-listing",
            "source_lang": "de",
            "target_lang": "en",
        },
    )
preview = response.json()
print(f"Rows: {preview['total_rows']}")

# Create jobs
with open("products.csv", "rb") as f:
    response = requests.post(
        "https://app.falara.io/v1/jobs/batch-csv",
        headers={"X-API-Key": FALARA_API_KEY},
        files={"file": ("products.csv", f)},
        data={
            "structure_template_id": "amazon-listing",
            "source_lang": "de",
            "target_lang": "en",
            "mapping_id": "map_abc123",
        },
    )
print(response.json())
// Dry run
const formData = new FormData();
formData.append("file", csvBlob, "products.csv");
formData.append("structure_template_id", "amazon-listing");
formData.append("source_lang", "de");
formData.append("target_lang", "en");

const preview = await fetch(
  "https://app.falara.io/v1/jobs/batch-csv?dry_run=true",
  {
    method: "POST",
    headers: { "X-API-Key": FALARA_API_KEY },
    body: formData,
  }
);
console.log(await preview.json());

// Create jobs
formData.append("mapping_id", "map_abc123");
const response = await fetch("https://app.falara.io/v1/jobs/batch-csv", {
  method: "POST",
  headers: { "X-API-Key": FALARA_API_KEY },
  body: formData,
});
console.log(await response.json());

Errors

Status Description
401 Invalid or missing API key.
404 Structure template not found.
422 Validation error (invalid CSV, missing required columns).
429 Rate limit or word quota exceeded.

POST /v1/jobs/batch-content

Submit structured JSON data for batch content creation using a Structure Template. Ideal for API integrations, Shopify apps, and other connectors that send structured product data.

Authentication

Header: X-API-Key: your_api_key

Content-Type: application/json Status: 202 Accepted

Request Body

Field Type Required Default Description
structure_template_id string yes -- Template ID or slug defining the output structure.
source_lang string yes -- BCP-47 source language code.
items array yes -- 1–5,000 items to process.
items[].data object yes -- Key-value pairs (like a CSV row). Must not be empty.
items[].metadata object no null Arbitrary JSON (max 4 KB). Stored on the job and returned unchanged in the result.
smart_mode boolean no false Auto-map all columns as product data. Requires Starter plan or higher.
column_map object no null Manual mapping {data_key: target_field}. Ignored when smart_mode is true.
project_name string no null Project label (max 100 characters).
glossary_id string no null Glossary ID to apply to all items in the batch.
glossary_ids string[] no null Multiple glossary IDs to apply (combined).

Request Example

{
  "structure_template_id": "product_short",
  "source_lang": "de-DE",
  "smart_mode": true,
  "project_name": "Shopify Import March",
  "items": [
    {
      "data": { "title": "Taucheruhr", "sku": "SKU-123", "material": "Edelstahl" },
      "metadata": { "resource_id": "gid://shopify/Product/123", "shop": "myshop" }
    },
    {
      "data": { "title": "Lederuhr", "sku": "SKU-456" },
      "metadata": { "resource_id": "gid://shopify/Product/456" }
    }
  ]
}

Response (202)

{
  "batch_id": "c9c851ae-03f3-4748-af1d-6859d9c5c79c",
  "total_items": 2,
  "jobs_created": 2,
  "job_ids": [
    "c118d515-944a-49c7-991e-761a43b4b97c",
    "9567d0d5-5846-4067-971a-9b0a3aeda629"
  ]
}

Metadata Passthrough

The metadata object for each item is stored on the job and returned in GET /v1/jobs/{job_id}/result as the item_metadata field. Use this to store external IDs (e.g., Shopify product GIDs) so you can map results back to source records.

Validation

All items are validated before any jobs are created. If validation fails, the entire request is rejected with all errors listed (up to 100):

{
  "detail": "Validation failed for 2 items",
  "errors": [
    { "index": 3, "field": "item[3].data", "message": "must be a non-empty object" },
    { "index": 7, "field": "item[7].metadata", "message": "exceeds 4KB limit" }
  ]
}

Examples

curl -X POST https://app.falara.io/api/v1/jobs/batch-content \
  -H "X-API-Key: $FALARA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "structure_template_id": "product_short",
    "source_lang": "de-DE",
    "smart_mode": true,
    "items": [
      {"data": {"title": "Taucheruhr", "sku": "SKU-1", "material": "Edelstahl"}},
      {"data": {"title": "Lederuhr", "sku": "SKU-2", "material": "Leder"}}
    ]
  }'
import requests

response = requests.post(
    "https://app.falara.io/api/v1/jobs/batch-content",
    headers={
        "X-API-Key": FALARA_API_KEY,
        "Content-Type": "application/json",
    },
    json={
        "structure_template_id": "product_short",
        "source_lang": "de-DE",
        "smart_mode": True,
        "items": [
            {"data": {"title": "Taucheruhr", "sku": "SKU-1"}, "metadata": {"id": "123"}},
            {"data": {"title": "Lederuhr", "sku": "SKU-2"}, "metadata": {"id": "456"}},
        ],
    },
)
batch = response.json()
print(f"Batch {batch['batch_id']}: {batch['jobs_created']} jobs created")
const response = await fetch("https://app.falara.io/api/v1/jobs/batch-content", {
  method: "POST",
  headers: {
    "X-API-Key": FALARA_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    structure_template_id: "product_short",
    source_lang: "de-DE",
    smart_mode: true,
    items: [
      { data: { title: "Taucheruhr", sku: "SKU-1" }, metadata: { id: "123" } },
      { data: { title: "Lederuhr", sku: "SKU-2" }, metadata: { id: "456" } },
    ],
  }),
});
const batch = await response.json();
console.log(`Batch ${batch.batch_id}: ${batch.jobs_created} jobs created`);

Errors

Status Description
400 Validation error (empty items, invalid data, metadata too large).
401 Invalid or missing API key.
403 Smart Mode requires a Starter plan or higher.
404 Structure template not found.
429 Rate limit or concurrent job limit reached.

GET /v1/jobs/batch/{batch_id}/export

Export all jobs in a batch as a CSV file. Useful for downloading results in bulk or importing into spreadsheets.

Authentication

Header: X-API-Key: your_api_key

Status: 200 OK Content-Type: text/csv; charset=utf-8

Query Parameters

Parameter Type Required Default Description
format string no csv Export format. Currently only csv is supported.

CSV Columns

Group Columns Source
Meta _job_id, _status, _smart_mode, _error Job record
Input Superset of all input keys across jobs briefing.input_material
Output out:<field> for each template field (alphabetical) segments[].text
  • Completed jobs: Output columns contain generated text.
  • Failed/queued jobs: Output columns are empty; _error contains the first error message.
  • Empty batch: Returns a CSV with headers only (no 404).

CSV Injection Protection

All cell values starting with =, +, -, or @ are prefixed with a single quote (') to prevent formula injection in Excel and Google Sheets.

Examples

curl -X GET "https://app.falara.io/api/v1/jobs/batch/c9c851ae-.../export?format=csv" \
  -H "X-API-Key: $FALARA_API_KEY" \
  -o batch_results.csv
import requests

response = requests.get(
    f"https://app.falara.io/api/v1/jobs/batch/{batch_id}/export",
    headers={"X-API-Key": FALARA_API_KEY},
    params={"format": "csv"},
)

with open("batch_results.csv", "w") as f:
    f.write(response.text)
const response = await fetch(
  `https://app.falara.io/api/v1/jobs/batch/${batchId}/export?format=csv`,
  { headers: { "X-API-Key": FALARA_API_KEY } }
);
const csv = await response.text();
console.log(csv);

Errors

Status Description
400 Unsupported format (only csv is supported).
401 Invalid or missing API key.

POST /v1/jobs/batch-text

Submit a text for translation into multiple target languages in a single request. One job is created per target language, all sharing a batch_id.

Authentication

Header: X-API-Key: your_api_key

Content-Type: application/json Status: 202 Accepted

Request Body

The request body is the same as POST /v1/jobs (text translation), but target_lang must be a list of language codes instead of a single string.

Field Type Required Default Description
source_lang string yes -- BCP-47 source language code.
target_lang string[] yes -- List of BCP-47 target language codes (max 10).
text string yes* -- Text to translate. *Either text or texts is required.
texts array yes* -- Array of strings or {text, metadata} objects (max 500).
domain string no null Domain hint (e.g., "legal", "medical", "ecommerce").
tone string no null Desired tone (e.g., "formal", "casual").
instructions string no null Custom instructions for the translator.
glossary_id string no null Glossary ID to apply.
quality string no "standard" "standard" or "premium" (Starter+ required).
project_name string no null Project label (max 100 characters).
glossary_id string no null Glossary ID to apply to all items in the batch.
glossary_ids string[] no null Multiple glossary IDs to apply (combined).

Request Example

{
  "source_lang": "de",
  "target_lang": ["en", "fr", "es"],
  "text": "Unsere Produkte stehen für höchste Qualität.",
  "domain": "ecommerce",
  "tone": "formal",
  "project_name": "Product Launch Q2"
}

Response (202)

{
  "batch_id": "b1c2d3e4-...",
  "jobs": [
    { "job_id": "550e8400-...", "target_lang": "en", "status": "queued" },
    { "job_id": "550e8401-...", "target_lang": "fr", "status": "queued" },
    { "job_id": "550e8402-...", "target_lang": "es", "status": "queued" }
  ]
}

Idempotency

Pass an Idempotency-Key header (max 64 characters) to safely retry requests. If the same key is used with the same request body within 24 hours, the original response is replayed.

Examples

curl -X POST https://app.falara.io/api/v1/jobs/batch-text \
  -H "X-API-Key: $FALARA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-unique-key-123" \
  -d '{
    "source_lang": "de",
    "target_lang": ["en", "fr", "es"],
    "text": "Unsere Produkte stehen für höchste Qualität.",
    "domain": "ecommerce"
  }'
import requests

response = requests.post(
    "https://app.falara.io/api/v1/jobs/batch-text",
    headers={
        "X-API-Key": FALARA_API_KEY,
        "Content-Type": "application/json",
    },
    json={
        "source_lang": "de",
        "target_lang": ["en", "fr", "es"],
        "text": "Unsere Produkte stehen für höchste Qualität.",
        "domain": "ecommerce",
    },
)
batch = response.json()
for job in batch["jobs"]:
    print(f"{job['target_lang']}: {job['job_id']} ({job['status']})")
const response = await fetch("https://app.falara.io/api/v1/jobs/batch-text", {
  method: "POST",
  headers: {
    "X-API-Key": FALARA_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    source_lang: "de",
    target_lang: ["en", "fr", "es"],
    text: "Unsere Produkte stehen für höchste Qualität.",
    domain: "ecommerce",
  }),
});
const batch = await response.json();
batch.jobs.forEach((job) =>
  console.log(`${job.target_lang}: ${job.job_id} (${job.status})`)
);

Errors

Status Description
401 Invalid or missing API key.
403 Premium quality requires a paid plan.
422 target_lang must be a list, is empty, contains duplicates, or includes source_lang.
422 Too many target languages (max 10).
429 Rate limit or concurrent job limit reached.