> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gnani.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Batch STT Introduction

> Asynchronous transcription of long or multiple audio files via the Batch Jobs API.

Use **STT Batch** to transcribe long recordings or many files asynchronously.

**Flow:** create a job → start it → poll until it finishes → download transcripts\
(or receive them on a webhook).

| If you need…                                       | Use                                    |
| -------------------------------------------------- | -------------------------------------- |
| Long files, many files, or offline pipelines       | **STT Batch** (this section)           |
| Short clips (under \~60 seconds), immediate answer | [STT REST](/api/STT/speech-to-text)    |
| Live microphone / streaming audio                  | [STT Realtime](/api/STT/stt-websocket) |

***

## How it works

```text theme={null}
1. CREATE    POST /stt/v3/batch/jobs
             → 201  job_id   status: CREATED

2. START     POST /stt/v3/batch/jobs/{job_id}/start
             → 202             status: STARTING

3. WAIT      GET  /stt/v3/batch/jobs/{job_id}
             poll every 10s until a terminal status
             (live: STARTING → QUEUED → IN_PROGRESS → COMPLETED)

4. FILES     GET  /stt/v3/batch/jobs/{job_id}/files
             → transcript_url for each completed file

5. DOWNLOAD  GET  <transcript_url>
             → JSON with full_transcript + segments
```

**Important:** creating a job does **not** start transcription. You must call `/start`.

***

## Interactive API reference

Each endpoint has a **Try it** playground. Paste your `X-API-Key-ID` and run live requests from the docs.

| Step | Endpoint                                  | Page                                         |
| ---- | ----------------------------------------- | -------------------------------------------- |
| 1    | `POST /stt/v3/batch/jobs`                 | [Create Job](/api/STTBatch/Create_Job)       |
| 2    | `POST /stt/v3/batch/jobs/{job_id}/start`  | [Start Job](/api/STTBatch/Start_Job)         |
| 3    | `GET /stt/v3/batch/jobs/{job_id}`         | [Get Job Status](/api/STTBatch/Get_Job)      |
| 4    | `GET /stt/v3/batch/jobs/{job_id}/files`   | [Get Job Files](/api/STTBatch/Get_Job_Files) |
| —    | `GET /stt/v3/batch/jobs`                  | [List Jobs](/api/STTBatch/List_Jobs)         |
| —    | `POST /stt/v3/batch/jobs/{job_id}/cancel` | [Cancel Job](/api/STTBatch/Cancel_Job)       |

**Webhook payload examples:** [Webhooks](#webhooks) — samples for `job.completed`, `job.failed`, and `job.cancelled`.

***

## Before you begin

1. An API key from the Gnani APIs dashboard
2. Audio with **real speech** in a [supported format](#supported-audio-formats)
3. A [supported language code](#supported-languages)

**Base URL**

```text theme={null}
https://api.vachana.ai
```

**Auth** — send on every Batch API request:

```http theme={null}
X-API-Key-ID: <YOUR_API_KEY>
```

Tone-only / silent audio is accepted into a job but fails later with `Empty transcript after 3 retries`.

***

## How do I get the transcript text?

| Option                   | When to use               | What you do                                                                           |
| ------------------------ | ------------------------- | ------------------------------------------------------------------------------------- |
| **A. Polling (default)** | No webhook                | Poll job status → `GET /files` → `GET` each `transcript_url` → read `full_transcript` |
| **B. Webhook**           | You passed `callback_url` | Receive a POST with `transcripts[]` including `full_transcript`                       |

`GET /jobs/{job_id}` and `GET /jobs/{job_id}/files` do **not** return `full_transcript`.

***

## Quickstart (live-verified)

### 1. Create

```bash theme={null}
curl --request POST \
  --url https://api.vachana.ai/stt/v3/batch/jobs \
  --header 'X-API-Key-ID: <YOUR_API_KEY>' \
  -F 'config={"model":"gnani-prisma-v2.5","language_code":"en-IN","mode":"transcribe","with_diarization":false,"is_multi_channel":false};type=application/json' \
  -F "files=@./customer_call.wav"
```

```json theme={null}
{
  "job_id": "019fa79e-81f9-7a8a-a446-6eff16ddec30",
  "status": "CREATED",
  "total_files_accepted": 1,
  "created_at": "2026-07-28T07:26:50.926489Z",
  "message": "1 file(s) uploaded. Call POST /v1/jobs/{job_id}/start to begin processing."
}
```

### 2. Start

```bash theme={null}
curl --request POST \
  --url https://api.vachana.ai/stt/v3/batch/jobs/019fa79e-81f9-7a8a-a446-6eff16ddec30/start \
  --header 'X-API-Key-ID: <YOUR_API_KEY>'
```

```json theme={null}
{
  "job_id": "019fa79e-81f9-7a8a-a446-6eff16ddec30",
  "status": "STARTING",
  "message": "Job start accepted. File validation and queueing are running in the background. Poll GET /stt/v3/batch/jobs/{job_id} to track progress."
}
```

### 3. Poll until `COMPLETED`

```bash theme={null}
curl --request GET \
  --url https://api.vachana.ai/stt/v3/batch/jobs/019fa79e-81f9-7a8a-a446-6eff16ddec30 \
  --header 'X-API-Key-ID: <YOUR_API_KEY>'
```

### 4. Get `transcript_url`, then download text

```bash theme={null}
curl --request GET \
  --url 'https://api.vachana.ai/stt/v3/batch/jobs/019fa79e-81f9-7a8a-a446-6eff16ddec30/files?status=COMPLETED' \
  --header 'X-API-Key-ID: <YOUR_API_KEY>'
```

```bash theme={null}
curl -L "<transcript_url>"
```

```json theme={null}
{
  "full_transcript": "hello how can i help you today i am calling about my recent order number 12345",
  "model": "gnani-prisma-v2.5",
  "language_code": "en-IN",
  "duration_seconds": 6.01
}
```

***

## Configuration

| Field              | Type    | Required                  | Default        | Description                                     |
| ------------------ | ------- | ------------------------- | -------------- | ----------------------------------------------- |
| `model`            | string  | Yes                       | —              | `"gnani-prisma-v2.5"`                           |
| `language_code`    | string  | Yes                       | —              | See [Supported languages](#supported-languages) |
| `mode`             | string  | No                        | `"transcribe"` | Use `"transcribe"` for now                      |
| `with_diarization` | boolean | No                        | `false`        | Enable speaker diarization                      |
| `num_speakers`     | integer | Yes, if diarization is on | —              | Max **2**                                       |
| `is_multi_channel` | boolean | No                        | `false`        | `true` only for true multi-channel audio        |

Inverse Text Normalization (ITN) is **not** supported for STT Batch.

***

## Limits

| Limit                     | Value                                       |
| ------------------------- | ------------------------------------------- |
| Max audio files per job   | **100**                                     |
| Max file size             | **10 MB** per file                          |
| Max ZIP compressed size   | **50 MB**                                   |
| Max ZIP decompressed size | **200 MB**                                  |
| `transcript_url` expiry   | **1 hour** (`X-Amz-Expires=3600`)           |
| Poll interval             | **≥ 10 s** (prefer **30 s** for 100+ files) |

***

## Supported languages

| Code    | Language             |
| ------- | -------------------- |
| `bn-BD` | Bengali (Bangladesh) |
| `bn-IN` | Bengali (India)      |
| `en-IN` | English (India)      |
| `hi-IN` | Hindi                |
| `kn-IN` | Kannada              |
| `ml-IN` | Malayalam            |
| `mr-IN` | Marathi              |
| `ta-IN` | Tamil                |
| `te-IN` | Telugu               |

***

## Supported audio formats

`.wav` · `.mp3` · `.mp4` · `.flac` · `.ogg` · `.opus` · `.m4a` · `.aac` · `.webm` · `.amr`

***

## Job statuses

| Status            | Terminal | Meaning                            |
| ----------------- | -------- | ---------------------------------- |
| `CREATED`         | No       | Waiting for `/start`               |
| `STARTING`        | No       | Setup running                      |
| `QUEUED`          | No       | Files queued                       |
| `IN_PROGRESS`     | No       | Transcription running              |
| `COMPLETED`       | Yes      | All succeeded                      |
| `PARTIAL_FAILURE` | Yes      | Mixed results                      |
| `FAILED`          | Yes      | Failed                             |
| `START_FAILED`    | Yes      | Setup failed — see `cancel_reason` |
| `CANCELLING`      | No       | Cancel in progress                 |
| `CANCELLED`       | Yes      | Cancelled                          |

***

## Webhooks

Pass `callback_url` at create time to receive a `POST` when the job reaches a terminal state.

| `event`               | Triggered when          |
| --------------------- | ----------------------- |
| `job.completed`       | All files succeeded     |
| `job.partial_failure` | Mixed success / failure |
| `job.failed`          | All files failed        |
| `job.cancelled`       | Job cancelled           |

The `transcripts` array includes full per-file transcript JSON (with `full_transcript`), so webhook users usually do not need `/files` + `transcript_url`.

Treat webhooks as best-effort. Polling remains the source of truth.

### Sample webhook payload — `job.completed`

```json theme={null}
{
  "event": "job.completed",
  "job_id": "019fa79e-81f9-7a8a-a446-6eff16ddec30",
  "org_id": "org_acme123",
  "user_id": "user_abc456",
  "status": "COMPLETED",
  "total_files": 1,
  "completed_files": 1,
  "failed_files": 0,
  "cancelled_files": 0,
  "completed_at": "2026-07-28T07:27:24Z",
  "callback_url": "https://yourapp.com/webhooks/stt",
  "transcripts": [
    {
      "file_id": "6f5e3bcd-add2-479c-8883-a9c27b221f10",
      "job_id": "019fa79e-81f9-7a8a-a446-6eff16ddec30",
      "original_path": "customer_call.wav",
      "language_code": "en-IN",
      "duration_seconds": 6.01,
      "model": "gnani-prisma-v2.5",
      "mode": "transcribe",
      "segments": [
        {
          "segment_id": 0,
          "start_time": 0.0,
          "end_time": 0.71,
          "text": "hello",
          "speaker_id": 1,
          "confidence": null,
          "language_detected": null,
          "sentiment": null,
          "emotion": null
        },
        {
          "segment_id": 0,
          "start_time": 0.71,
          "end_time": 2.36,
          "text": "how can i help you today",
          "speaker_id": 2,
          "confidence": null,
          "language_detected": null,
          "sentiment": null,
          "emotion": null
        },
        {
          "segment_id": 0,
          "start_time": 2.36,
          "end_time": 6.01,
          "text": "i am calling about my recent order number 12345",
          "speaker_id": 2,
          "confidence": null,
          "language_detected": null,
          "sentiment": null,
          "emotion": null
        }
      ],
      "full_transcript": "hello how can i help you today i am calling about my recent order number 12345",
      "created_at": "2026-07-28T07:27:24Z"
    }
  ]
}
```

### Sample webhook payload — `job.failed`

```json theme={null}
{
  "event": "job.failed",
  "job_id": "019fa79b-a07a-7a3e-93bf-4ee73974dfa2",
  "org_id": "org_acme123",
  "user_id": "user_abc456",
  "status": "FAILED",
  "total_files": 1,
  "completed_files": 0,
  "failed_files": 1,
  "cancelled_files": 0,
  "completed_at": "2026-07-28T07:24:32Z",
  "callback_url": "https://yourapp.com/webhooks/stt",
  "transcripts": []
}
```

### Sample webhook payload — `job.cancelled`

```json theme={null}
{
  "event": "job.cancelled",
  "job_id": "019fa79c-7880-7d05-a528-edc7892ad9ea",
  "org_id": "org_acme123",
  "user_id": "user_abc456",
  "status": "CANCELLED",
  "total_files": 1,
  "completed_files": 0,
  "failed_files": 0,
  "cancelled_files": 1,
  "completed_at": null,
  "callback_url": "https://yourapp.com/webhooks/stt",
  "transcripts": []
}
```

***

## Common mistakes

| Mistake                                        | What happens                                  | Fix                                                  |
| ---------------------------------------------- | --------------------------------------------- | ---------------------------------------------------- |
| Forgetting `/start`                            | Job stays `CREATED`                           | Call [Start Job](/api/STTBatch/Start_Job)            |
| Expecting `full_transcript` on status/`/files` | Field missing                                 | `GET /files` → then `GET transcript_url`             |
| Using `/v1/jobs/...` from create message       | Wrong path                                    | Use `/stt/v3/batch/jobs/{job_id}/start`              |
| Uploading silence / tones                      | `FAILED` — `Empty transcript after 3 retries` | Use real speech                                      |
| Invalid public URL                             | `START_FAILED` / file `SKIPPED`               | Use reachable HTTPS URLs                             |
| Polling every 1–2 seconds                      | Wasted calls                                  | Poll every 10s                                       |
| Expired `transcript_url`                       | Download fails                                | Re-call [Get Job Files](/api/STTBatch/Get_Job_Files) |

***

## Support

Docs feedback: [Batch STT docs feedback](https://discord.com/channels/1511338519899930634/1515991436229611571)

**Last verified:** 28 Jul 2026 against `https://api.vachana.ai`\
Live-checked: Create → Start → Poll → Files → Transcript download, List, Cancel, and error codes `401` / `400` / `404` / `409`.
