Skip to content

Endpoint: Batch Processing ​

Submit high-volume, non-time-sensitive workloads at 50% cost savings by leveraging provider-native batch APIs (OpenAI, Anthropic, Gemini). VeriPrompt routes your batch to the optimal provider or splits it across multiple providers for cost optimization.

  • Base URL: https://<your-domain>/api/v1
  • Content-Type: application/json or multipart/form-data
  • Authentication: Session cookie or API key

Core Concepts ​

Batch Lifecycle ​

QUEUED -> VALIDATING -> PROCESSING -> COMPLETED
                                   -> FAILED
                                   -> CANCELLED
                                   -> EXPIRED
StatusDescription
QUEUEDJob created, waiting for background processor to pick it up
VALIDATINGItems being validated and formatted for the provider
PROCESSINGSubmitted to provider, awaiting results
COMPLETEDAll items processed (some may have individual errors)
FAILEDJob-level failure (e.g., no provider found, auth error)
CANCELLEDCancelled by user
EXPIREDResults expired after TTL (default 30 days)

Item Status ​

Each item within a batch has its own status:

StatusDescription
PENDINGAwaiting processing
PROCESSINGCurrently being processed
SUCCESSCompleted successfully
ERRORFailed with error
SKIPPEDNo result received from provider

Split Strategies ​

When multiple providers are available, batches can be split:

StrategyBehavior
singleAll items sent to the best provider (default)
round-robinItems distributed evenly across available providers
cost-optimalMore items allocated to cheaper providers

POST /api/v1/batch ​

Submit a new batch job. Accepts either JSON body with inline items or multipart form data with a JSONL file.

JSON Request Body ​

typescript
{
  items: Array<{
    id: string;          // Unique ID for this item (used in results)
    prompt: string;      // The prompt text (required)
    systemPrompt?: string;
    variables?: Record<string, string>; // For {{variable}} substitution
  }>;
  config?: {
    name?: string;                    // Display name for the batch
    routingPolicyId?: string;         // Use a specific routing policy
    qualityTier?: "cheap" | "fast" | "quality" | "secure";
    providerHint?: string;            // Prefer this provider (e.g., "openai")
    model?: string;                   // Specific model (e.g., "gpt-4o")
    sanitization?: boolean;           // Enable PII sanitization
    splitStrategy?: "single" | "round-robin" | "cost-optimal";
    callbackUrl?: string;             // Webhook URL for completion notification
    metadata?: Record<string, any>;   // Custom metadata
  };
}

Multipart Form Data ​

FieldTypeDescription
fileFileJSONL file (one JSON object per line), up to 100MB
configStringJSON string with configuration options (same as config above)

JSONL File Format ​

Each line must be a valid JSON object with at least id and prompt:

jsonl
{"id": "req-1", "prompt": "Summarize this article in 3 sentences.", "systemPrompt": "You are a helpful assistant."}
{"id": "req-2", "prompt": "Translate to French: Hello, how are you?"}
{"id": "req-3", "prompt": "Extract entities from: {{text}}", "variables": {"text": "Apple was founded by Steve Jobs."}}

Response (201 Created) ​

json
{
  "batchId": "cm1abc123def456",
  "status": "QUEUED",
  "totalItems": 3,
  "estimatedCostUSD": null,
  "createdAt": "2026-03-05T12:00:00.000Z"
}

Example: cURL (JSON inline) ​

bash
curl -X POST https://app.veriprompt.tech/api/v1/batch \
  -H "Content-Type: application/json" \
  -H "Cookie: next-auth.session-token=YOUR_SESSION" \
  -d '{
    "items": [
      {"id": "q1", "prompt": "What is 2+2?"},
      {"id": "q2", "prompt": "Capital of France?"},
      {"id": "q3", "prompt": "Explain quantum computing in one sentence."}
    ],
    "config": {
      "name": "eval-run-2026-03",
      "qualityTier": "cheap",
      "splitStrategy": "single"
    }
  }'

Example: cURL (JSONL file upload) ​

bash
curl -X POST https://app.veriprompt.tech/api/v1/batch \
  -H "Cookie: next-auth.session-token=YOUR_SESSION" \
  -F "file=@batch_requests.jsonl" \
  -F 'config={"name":"file-upload-batch","providerHint":"openai"}'

Example: TypeScript ​

typescript
const response = await fetch('/api/v1/batch', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    items: [
      { id: 'item-1', prompt: 'Summarize this text: ...' },
      { id: 'item-2', prompt: 'Translate to Spanish: ...' },
    ],
    config: {
      name: 'my-batch-job',
      qualityTier: 'cheap',
      callbackUrl: 'https://myapp.com/webhook/batch-complete',
    },
  }),
});

const { batchId, status, totalItems } = await response.json();
console.log(`Batch ${batchId} created with ${totalItems} items`);

Error Responses ​

StatusErrorCondition
400Missing itemsNo items array or no file in form data
400Validation failedItems exceed max count (50,000) or file exceeds size limit
400Invalid configConfig fields fail validation
401UnauthorizedNo valid session or API key
429CONCURRENT_LIMITToo many active batch jobs (default max: 10)

GET /api/v1/batch ​

List batch jobs for the authenticated user's company.

Query Parameters ​

ParameterTypeDefaultDescription
statusstring—Filter by status (e.g., COMPLETED, PROCESSING)
limitnumber20Max results (capped at 100)
offsetnumber0Pagination offset

Response (200) ​

json
{
  "jobs": [
    {
      "id": "cm1abc123def456",
      "name": "eval-run-2026-03",
      "status": "COMPLETED",
      "totalItems": 100,
      "completedItems": 98,
      "failedItems": 2,
      "providerName": "openai",
      "estimatedCostUSD": 0.0250,
      "actualCostUSD": 0.0243,
      "createdAt": "2026-03-05T12:00:00.000Z",
      "startedAt": "2026-03-05T12:00:05.000Z",
      "completedAt": "2026-03-05T12:05:30.000Z"
    }
  ],
  "total": 15,
  "limit": 20,
  "offset": 0
}

Example: cURL ​

bash
curl "https://app.veriprompt.tech/api/v1/batch?status=COMPLETED&limit=10" \
  -H "Cookie: next-auth.session-token=YOUR_SESSION"

GET /api/v1/batch/:batchId ​

Get detailed information about a specific batch job.

Response (200) ​

json
{
  "batchId": "cm1abc123def456",
  "name": "eval-run-2026-03",
  "status": "COMPLETED",
  "totalItems": 100,
  "completedItems": 98,
  "failedItems": 2,
  "progress": 1.0,
  "providerName": "openai",
  "providerModel": "gpt-4o-mini",
  "splitStrategy": "single",
  "qualityTier": "cheap",
  "sanitizationEnabled": false,
  "estimatedCostUSD": 0.0250,
  "actualCostUSD": 0.0243,
  "inputTokensTotal": 15000,
  "outputTokensTotal": 12000,
  "createdAt": "2026-03-05T12:00:00.000Z",
  "startedAt": "2026-03-05T12:00:05.000Z",
  "completedAt": "2026-03-05T12:05:30.000Z",
  "expiresAt": "2026-04-04T12:00:05.000Z",
  "errorMessage": null,
  "splits": [
    {
      "id": "split-1",
      "providerName": "openai",
      "providerModel": "gpt-4o-mini",
      "itemCount": 100,
      "status": "COMPLETED",
      "costUSD": 0.0243
    }
  ],
  "metadata": {}
}

Error Responses ​

StatusErrorCondition
404Not foundBatch ID doesn't exist or belongs to different company
401UnauthorizedNo valid session

GET /api/v1/batch/:batchId/results ​

Download results for a completed batch. Supports JSON and JSONL formats.

Query Parameters ​

ParameterTypeDefaultDescription
statusstring—Filter items by status (SUCCESS, ERROR, SKIPPED)
limitnumber—Limit number of results
offsetnumber0Pagination offset

Headers ​

HeaderValueEffect
Acceptapplication/jsonReturns JSON array (default)
Acceptapplication/jsonlReturns JSONL file with Content-Disposition header

JSON Response (200) ​

json
{
  "items": [
    {
      "externalId": "q1",
      "sequenceIndex": 0,
      "status": "SUCCESS",
      "response": "2+2 equals 4.",
      "inputTokens": 12,
      "outputTokens": 8,
      "costUSD": 0.0001
    },
    {
      "externalId": "q2",
      "sequenceIndex": 1,
      "status": "ERROR",
      "errorCode": "RATE_LIMIT",
      "errorMessage": "Provider rate limit exceeded"
    }
  ],
  "total": 100,
  "limit": 100,
  "offset": 0
}

Example: Download JSONL ​

bash
curl "https://app.veriprompt.tech/api/v1/batch/cm1abc123/results" \
  -H "Accept: application/jsonl" \
  -H "Cookie: next-auth.session-token=YOUR_SESSION" \
  -o results.jsonl

POST /api/v1/batch/:batchId/cancel ​

Cancel an active batch job. Works for jobs in QUEUED, VALIDATING, or PROCESSING status.

Response (200) ​

json
{
  "batchId": "cm1abc123def456",
  "status": "CANCELLED"
}

Error Responses ​

StatusErrorCondition
400Cannot cancelJob is already completed, cancelled, or expired
404Not foundBatch ID doesn't exist

Background Processing ​

Batch jobs are processed by a background cron job that runs every 60 seconds:

POST /api/internal/batch/process
x-internal-job: <INTERNAL_JOB_TOKEN>

The processor:

  1. Picks up QUEUED jobs (up to 5 at a time)
  2. Resolves the optimal provider from the company's provider group or BYOK credentials
  3. Submits items to the provider's native batch API
  4. Polls PROCESSING jobs for completion
  5. Fetches and stores results on completion
  6. Fires webhook if callbackUrl was configured
  7. Logs usage to billing (UsageLog + CompanyPackage)

Webhook Notification ​

When a batch completes and callbackUrl was set, VeriPrompt sends:

json
POST <callbackUrl>
Content-Type: application/json

{
  "batchId": "cm1abc123def456",
  "status": "COMPLETED",
  "completedItems": 98,
  "failedItems": 2,
  "actualCostUSD": 0.0243,
  "resultsUrl": "https://app.veriprompt.tech/api/v1/batch/cm1abc123def456/results"
}

Configuration ​

Environment VariableDefaultDescription
BATCH_MAX_FILE_SIZE_MB100Maximum JSONL upload size in MB
BATCH_MAX_ITEMS50000Maximum items per batch
BATCH_RESULTS_TTL_DAYS30Auto-expire results after N days
BATCH_MAX_CONCURRENT_JOBS10Max active jobs per company
BATCH_WEBHOOK_TIMEOUT_MS10000Webhook delivery timeout
BATCH_MAX_RETRY_ATTEMPTS2Max retry attempts for failed items

Provider Support ​

ProviderBatch APIDiscountMax ItemsNotes
OpenAINative (/v1/batches)50%50,00024h completion window
AnthropicNative (Message Batches)50%10,000Streaming results
Gemini/GoogleConcurrent execution50%50,00020-request concurrency