NetraFlow
API Reference

Batch

Submit many videos in one request and track them as a unit.

A batch runs the same capabilities across many videos and reports progress as a unit. Batches can also answer aggregate questions spanning every video in the set.

Batch size is plan-gated: Free has no batch access (BATCH_NOT_ALLOWED, 403). Starter allows 10 videos per batch, Pro 25, Scale 50.

POST /v1/batch

Request body

Provide urls, uploads, or both — at least one source in total.

PropTypeDescription
urlsstring[]Video URLs. Max 50, and no more than your plan allows across urls + uploads combined.
uploadsUploadRef[]Uploaded files as { key, filename, duration_seconds? }, using keys from POST /v1/uploads/presign.
capabilitiesstring[]One or more of: transcription, summary, brands, metadata. Applied to every video in the batch.
queriesstring[]Per-video custom questions. Max 500 chars each.
aggregate{ enabled, queries? }Cross-video questions answered once for the whole batch. Capped by your plan's max_aggregate_queries_per_batch (0 on Free and Starter).
webhook_urlstringHTTPS URL for batch.completed and batch.paused delivery. Starter and above.
return_proofbooleanInclude visual evidence, as on single jobs. Defaults to true.
dry_runbooleanReturn the per-job and total cost estimate with HTTP 200 and create nothing. Defaults to false.
max_creditsintegerReject with BUDGET_EXCEEDED (402) if the total estimate exceeds this cap.
curl -X POST https://api.netraflow.com/v1/batch \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: sk_live_your_key_here" \
  -d '{
    "urls": [
      "https://www.youtube.com/watch?v=example1",
      "https://www.tiktok.com/@user/video/example2"
    ],
    "capabilities": ["brands"],
    "brands": ["Nike"],
    "aggregate": { "enabled": true, "queries": ["Which brand appears most often?"] }
  }'
{
  "data": {
    "batch_id": "bat_abc123",
    "status": "processing",
    "total_credits_estimated": 52,
    "balance": 400,
    "would_exceed_balance": false,
    "jobs": [
      {
        "job_id": "job_aaa",
        "url": "https://www.youtube.com/watch?v=example1",
        "platform": "youtube",
        "duration_seconds": null,
        "credits_estimated": 26,
        "status": "pending",
        "note": "duration_unresolved"
      },
      {
        "job_id": "job_bbb",
        "url": "https://www.tiktok.com/@user/video/example2",
        "platform": "tiktok",
        "duration_seconds": null,
        "credits_estimated": 26,
        "status": "pending"
      }
    ]
  },
  "meta": { "request_id": "req_xyz789" }
}

would_exceed_balance is a warning, not a rejection — the batch is still created. Jobs that can't be afforded once their real duration is known move to held and the batch reports paused. Use dry_run: true to price a batch without creating it (the response omits batch_id and per-job job_id/status).


GET /v1/batch/:id

curl https://api.netraflow.com/v1/batch/bat_abc123 \
  -H "X-Api-Key: sk_live_your_key_here"
{
  "data": {
    "batch_id": "bat_abc123",
    "status": "paused",
    "total_jobs": 10,
    "completed_count": 4,
    "failed_count": 0,
    "rollup": {
      "total": 10,
      "pending": 0,
      "processing": 0,
      "completed": 4,
      "held": 6,
      "failed": 0,
      "cancelled": 0
    },
    "credits_estimated": 260,
    "credits_charged": 104,
    "jobs": [
      {
        "job_id": "job_aaa",
        "status": "held",
        "url": "https://www.youtube.com/watch?v=example1",
        "credits_estimated": 26,
        "reason": "insufficient_credits"
      }
    ],
    "aggregate_results": null,
    "webhook_url": null,
    "created_at": "2026-04-03T12:00:00.000Z",
    "completed_at": null
  },
  "meta": { "request_id": "req_abc456" }
}

Prefer rollup over completed_count / failed_count — the legacy counters can't represent held.

Batch status values

PropTypeDescription
processingstringAt least one job is pending or processing.
pausedstringNon-terminal. No runnable jobs remain and at least one is held for credits. Add credits and the batch resumes automatically.
completedstringEvery job reached a terminal state.
failedstringThe batch as a whole failed.
cancelledstringThe batch was cancelled.

GET /v1/batch

List batches with cursor-based pagination. Accepts status, limit (1-100, default 20), and cursor.

curl "https://api.netraflow.com/v1/batch?status=completed&limit=10" \
  -H "X-Api-Key: sk_live_your_key_here"

POST /v1/batch/:id/cancel

Cancels the batch and every pending, processing, or held job in it. Idempotent — cancelling an already-cancelled batch succeeds without changing anything.

curl -X POST https://api.netraflow.com/v1/batch/bat_abc123/cancel \
  -H "X-Api-Key: sk_live_your_key_here"

The response reports cancelled_jobs. Jobs already completed are untouched and remain charged.


Error codes

CodeHTTPDescription
BATCH_NOT_ALLOWED403Batch is not available on your plan (Free)
TOO_MANY_URLS422More sources than your plan's max_batch_size
TOO_MANY_AGGREGATE_QUERIES422Exceeds max_aggregate_queries_per_batch
BATCH_NOT_FOUND404Batch does not exist or belongs to another workspace
BATCH_NOT_CANCELLABLE409Batch is already in a terminal state

Single-job error codes apply to the jobs inside a batch. See Jobs.

On this page