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

# Get Transcription Job by ID

> Retrieve the status and results of a video transcription job

## Overview

This endpoint retrieves the current status and results of a transcription job using its unique job ID. While processing is in progress, it returns the current job status. Once the job completes, it returns the full transcript data including word-level timing, speaker identification, and subtitle formats (SRT, VTT).

<Note>
  A valid API key is required to use this endpoint. Obtain your API key from the [API Access page](https://app.pictory.ai/api-access) in your Pictory dashboard.
</Note>

***

## API Endpoint

```http theme={null}
GET https://api.pictory.ai/pictoryapis/v1/jobs/{jobid}
```

***

## Request Parameters

### Path Parameters

<ParamField path="jobid" type="uuid" required>
  The unique identifier (UUID) of the transcription job. This value is the `jobId` returned by the [Video Transcription](/api-reference/transcription/video-transcription) endpoint.

  **Example:** `"cbbc5305-3c1c-46f0-bdde-468e5ecd763f"`
</ParamField>

### Headers

<ParamField header="Authorization" type="string" required>
  API key for authentication (starts with `pictai_`)

  ```
  Authorization: YOUR_API_KEY
  ```
</ParamField>

***

## Response

### In-Progress Response

Returned while the transcription is still being processed:

<ResponseField name="job_id" type="string">
  The unique identifier of the transcription job
</ResponseField>

<ResponseField name="success" type="boolean">
  `true` while the job is processing
</ResponseField>

<ResponseField name="data" type="object">
  <ResponseField name="status" type="string">
    `"in-progress"`: transcription is still being processed
  </ResponseField>
</ResponseField>

### Completed Response

Returned when the transcription has finished successfully. The response contains the full transcript data:

<ResponseField name="success" type="boolean">
  `true` when the job has completed successfully
</ResponseField>

<ResponseField name="job_id" type="string">
  The unique identifier of the transcription job
</ResponseField>

<ResponseField name="data" type="object">
  Contains the complete transcription results.

  <Expandable title="Transcript fields">
    <ResponseField name="transcript" type="array">
      Array of transcript segments with speaker identification and word-level timing.

      Each segment contains:

      <ResponseField name="uid" type="string">
        Unique identifier for the transcript segment
      </ResponseField>

      <ResponseField name="speakerId" type="integer">
        Speaker identifier for this segment
      </ResponseField>

      <ResponseField name="words" type="array">
        Array of word objects with precise timing information

        <ResponseField name="uid" type="string">
          Unique identifier for the word
        </ResponseField>

        <ResponseField name="word" type="string">
          The spoken word text. An empty string indicates a pause marker.
        </ResponseField>

        <ResponseField name="start_time" type="number">
          Start time in seconds
        </ResponseField>

        <ResponseField name="end_time" type="number">
          End time in seconds
        </ResponseField>

        <ResponseField name="speakerId" type="integer">
          Speaker identifier
        </ResponseField>

        <ResponseField name="sentence_index" type="integer">
          Index of the sentence this word belongs to
        </ResponseField>

        <ResponseField name="is_pause" type="boolean">
          `true` if this entry represents a pause rather than a spoken word
        </ResponseField>

        <ResponseField name="pause_size" type="string">
          Size of the pause (e.g., `"small"`). Present only when `is_pause` is `true`.
        </ResponseField>

        <ResponseField name="state" type="string">
          State of the word (e.g., `"active"`). Present only for pause markers.
        </ResponseField>
      </ResponseField>
    </ResponseField>

    <ResponseField name="url" type="string">
      URL of the original media file that was transcribed
    </ResponseField>

    <ResponseField name="mediaInfo" type="object">
      Metadata about the source media file

      <ResponseField name="duration" type="number">
        Duration of the media file in seconds
      </ResponseField>

      <ResponseField name="width" type="integer">
        Video width in pixels
      </ResponseField>

      <ResponseField name="height" type="integer">
        Video height in pixels
      </ResponseField>

      <ResponseField name="aspect_ratio" type="string">
        Aspect ratio label (e.g., `"sixteen-nine"`)
      </ResponseField>

      <ResponseField name="aspect_ratio_value" type="number">
        Numeric aspect ratio value (e.g., `1.7777777777777777`)
      </ResponseField>
    </ResponseField>

    <ResponseField name="txt" type="string">
      Full transcript as plain text
    </ResponseField>

    <ResponseField name="srt" type="string">
      Transcript in SRT subtitle format
    </ResponseField>

    <ResponseField name="vtt" type="string">
      Transcript in WebVTT subtitle format
    </ResponseField>

    <ResponseField name="language" type="string">
      Language code of the transcription (e.g., `"en-US"`)
    </ResponseField>
  </Expandable>
</ResponseField>

### Response Examples

<ResponseExample>
  ```json 200 - In Progress theme={null}
  {
      "job_id": "cbbc5305-3c1c-46f0-bdde-468e5ecd763f",
      "success": true,
      "data": {
          "status": "in-progress"
      }
  }
  ```

  ```json 200 - Completed theme={null}
  {
      "success": true,
      "data": {
          "transcript": [
              {
                  "uid": "1c01b891-9cfe-452d-8eb9-d1c82f58b44f",
                  "speakerId": 1,
                  "words": [
                      {
                          "uid": "21247197-328d-4fa7-9e97-b8f661093438",
                          "word": "",
                          "start_time": 0,
                          "end_time": 0.64,
                          "sentence_index": 0,
                          "is_pause": true,
                          "pause_size": "small",
                          "state": "active",
                          "speakerId": 1
                      },
                      {
                          "uid": "031b6091-08c5-436d-ad92-7da64ebbb9c5",
                          "word": "Click",
                          "start_time": 0.64,
                          "end_time": 0.96,
                          "speakerId": 1,
                          "sentence_index": 0
                      },
                      {
                          "uid": "6fdf6f9e-8b50-4e32-b09b-9d59a8e4d18c",
                          "word": "the",
                          "start_time": 0.96,
                          "end_time": 1.12,
                          "speakerId": 1,
                          "sentence_index": 0
                      },
                      {
                          "uid": "bfad854f-9a5e-4dd3-b6cf-afba0f8a0c9e",
                          "word": "play",
                          "start_time": 1.12,
                          "end_time": 1.36,
                          "speakerId": 1,
                          "sentence_index": 0
                      },
                      {
                          "uid": "1e56a014-74f0-4753-bfd5-1a6c6f91d40b",
                          "word": "button",
                          "start_time": 1.36,
                          "end_time": 1.68,
                          "speakerId": 1,
                          "sentence_index": 0
                      },
                      {
                          "uid": "c8ec17f0-d3cc-4445-9b5d-83de96cc3d28",
                          "word": "to",
                          "start_time": 1.68,
                          "end_time": 1.92,
                          "speakerId": 1,
                          "sentence_index": 0
                      },
                      {
                          "uid": "b6d56fc4-32e1-4121-9254-09db58f4861b",
                          "word": "watch",
                          "start_time": 1.92,
                          "end_time": 2.159,
                          "speakerId": 1,
                          "sentence_index": 0
                      },
                      {
                          "uid": "4f55e95c-e337-422c-9df0-753dbda7071e",
                          "word": "the",
                          "start_time": 2.159,
                          "end_time": 2.399,
                          "speakerId": 1,
                          "sentence_index": 0
                      },
                      {
                          "uid": "804a4882-ac3f-4972-814b-69c29b0eaab6",
                          "word": "tutorial.",
                          "start_time": 2.399,
                          "end_time": 2.899,
                          "speakerId": 1,
                          "sentence_index": 0
                      }
                  ]
              },
              {
                  "uid": "bdd8ec04-abeb-4c23-8187-b8a16239b4e3",
                  "speakerId": 1,
                  "words": [
                      {
                          "uid": "eaf3f3f9-a90d-42e2-9e47-c75719b58480",
                          "word": "It's",
                          "start_time": 5.04,
                          "end_time": 5.359,
                          "speakerId": 1,
                          "sentence_index": 2
                      },
                      {
                          "uid": "3f859d6e-39d2-4dfc-94d6-0dc99711e988",
                          "word": "Jimmy",
                          "start_time": 5.359,
                          "end_time": 5.68,
                          "speakerId": 1,
                          "sentence_index": 2
                      },
                      {
                          "uid": "7eae2d17-f3ff-4f09-aa7f-71969c6f0bc4",
                          "word": "from",
                          "start_time": 5.68,
                          "end_time": 5.92,
                          "speakerId": 1,
                          "sentence_index": 2
                      },
                      {
                          "uid": "b0dbd4b8-2aaa-4a87-9cc9-11385f2199f6",
                          "word": "Victory,",
                          "start_time": 5.92,
                          "end_time": 6.399,
                          "speakerId": 1,
                          "sentence_index": 2
                      }
                  ]
              }
          ],
          "url": "https://pictory-api-prod.s3.us-east-2.amazonaws.com/2sc7gb6gnnobemlp4jf6u3fdh8/e778154d-56c5-4e00-a2ec-0c06fced116a.mp4",
          "mediaInfo": {
              "duration": 451.16,
              "width": 1920,
              "aspect_ratio": "sixteen-nine",
              "aspect_ratio_value": 1.7777777777777777,
              "height": 1080
          },
          "txt": "Click the play button to watch the tutorial. Hey. It's Jimmy from Victory, and this is a demo of the AI video editor tool...",
          "srt": "1\n00:00:00,640 --> 00:00:02,899\nClick the play button to watch the tutorial.\n\n2\n00:00:04,639 --> 00:00:06,879\nHey. It's Jimmy from Victory, and this is\n\n3\n00:00:06,879 --> 00:00:09,939\na demo of the AI video editor tool.\n...",
          "vtt": "WEBVTT\n\n1\n00:00:00.640 --> 00:00:02.899\n- Click the play button to watch the tutorial.\n\n2\n00:00:04.639 --> 00:00:06.879\n- Hey. It's Jimmy from Victory, and this is\n...",
          "language": "en-US"
      },
      "job_id": "bb94a94d-32b2-46d0-a541-7021d648f884"
  }
  ```

  ```json 401 - Unauthorized theme={null}
  {
      "message": "Unauthorized"
  }
  ```

  ```json 200 - Invalid Job ID theme={null}
  {
      "id": "cbbc5305-3c1c-46f0-bdde-468e5ecd763f",
      "success": false,
      "data": {
          "error_code": "5000",
          "error_message": "JOB_NOT_FOUND"
      }
  }
  ```
</ResponseExample>

***

## Code Examples

<Tip>
  Replace `YOUR_API_KEY` with your actual API key and use the `jobId` returned from the [Video Transcription](/api-reference/transcription/video-transcription) endpoint.
</Tip>

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://api.pictory.ai/pictoryapis/v1/jobs/cbbc5305-3c1c-46f0-bdde-468e5ecd763f' \
    --header 'Authorization: YOUR_API_KEY' \
    --header 'accept: application/json' | python -m json.tool
  ```

  ```python Python theme={null}
  import requests
  import time

  def poll_transcription_job(api_key, job_id, max_wait=600, poll_interval=15):
      """
      Poll for transcription job completion.

      Args:
          api_key: Your Pictory API key
          job_id: The transcription job ID
          max_wait: Maximum wait time in seconds (default 10 minutes)
          poll_interval: Polling interval in seconds (default 15 seconds)
      """
      url = f"https://api.pictory.ai/pictoryapis/v1/jobs/{job_id}"
      headers = {
          "Authorization": api_key,
          "accept": "application/json"
      }

      start_time = time.time()

      while time.time() - start_time < max_wait:
          response = requests.get(url, headers=headers)
          data = response.json()

          if not data.get("success"):
              print("Job failed")
              return data

          status = data.get("data", {}).get("status")

          if status == "in-progress":
              print(f"Transcription in progress... (elapsed: {int(time.time() - start_time)}s)")
              time.sleep(poll_interval)
              continue

          # Job completed - transcript data is available
          transcript_data = data.get("data", {})
          print(f"Transcription complete!")
          print(f"Language: {transcript_data.get('language')}")
          print(f"Duration: {transcript_data.get('mediaInfo', {}).get('duration')}s")
          print(f"Segments: {len(transcript_data.get('transcript', []))}")
          return data

      print("Timeout waiting for transcription")
      return None

  # Usage
  result = poll_transcription_job("YOUR_API_KEY", "cbbc5305-3c1c-46f0-bdde-468e5ecd763f")

  if result and result.get("success"):
      data = result["data"]
      # Access the plain text transcript
      print(f"\nTranscript:\n{data.get('txt', '')[:500]}...")

      # Access SRT subtitles
      srt = data.get("srt", "")
      print(f"\nSRT preview:\n{srt[:300]}...")
  ```

  ```javascript JavaScript theme={null}
  const jobId = 'cbbc5305-3c1c-46f0-bdde-468e5ecd763f';

  async function pollTranscriptionJob(apiKey, jobId, maxWait = 600000, pollInterval = 15000) {
    const url = `https://api.pictory.ai/pictoryapis/v1/jobs/${jobId}`;
    const startTime = Date.now();

    while (Date.now() - startTime < maxWait) {
      const response = await fetch(url, {
        method: 'GET',
        headers: {
          'Authorization': apiKey,
          'accept': 'application/json'
        }
      });

      const data = await response.json();

      if (!data.success) {
        console.log('Job failed');
        return data;
      }

      const status = data.data?.status;

      if (status === 'in-progress') {
        console.log(`Transcription in progress... (${Math.round((Date.now() - startTime) / 1000)}s)`);
        await new Promise(resolve => setTimeout(resolve, pollInterval));
        continue;
      }

      // Job completed
      console.log('Transcription complete!');
      console.log(`Language: ${data.data.language}`);
      console.log(`Duration: ${data.data.mediaInfo?.duration}s`);
      console.log(`Segments: ${data.data.transcript?.length}`);
      return data;
    }

    console.log('Timeout waiting for transcription');
    return null;
  }

  // Usage
  const result = await pollTranscriptionJob('YOUR_API_KEY', jobId);

  if (result?.success) {
    console.log(`\nTranscript: ${result.data.txt?.substring(0, 500)}...`);
  }
  ```

  ```php PHP theme={null}
  <?php
  function pollTranscriptionJob($apiKey, $jobId, $maxWait = 600, $pollInterval = 15) {
      $url = "https://api.pictory.ai/pictoryapis/v1/jobs/{$jobId}";
      $startTime = time();

      while (time() - $startTime < $maxWait) {
          $ch = curl_init($url);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, [
              'Authorization: ' . $apiKey,
              'accept: application/json'
          ]);

          $response = curl_exec($ch);
          curl_close($ch);

          $data = json_decode($response, true);

          if (!$data['success']) {
              echo "Job failed\n";
              return $data;
          }

          $status = $data['data']['status'] ?? null;

          if ($status === 'in-progress') {
              $elapsed = time() - $startTime;
              echo "Transcription in progress... ({$elapsed}s)\n";
              sleep($pollInterval);
              continue;
          }

          // Job completed
          echo "Transcription complete!\n";
          echo "Language: " . ($data['data']['language'] ?? 'unknown') . "\n";
          echo "Duration: " . ($data['data']['mediaInfo']['duration'] ?? 0) . "s\n";
          echo "Segments: " . count($data['data']['transcript'] ?? []) . "\n";
          return $data;
      }

      echo "Timeout waiting for transcription\n";
      return null;
  }

  // Usage
  $result = pollTranscriptionJob('YOUR_API_KEY', 'cbbc5305-3c1c-46f0-bdde-468e5ecd763f');

  if ($result && $result['success']) {
      echo "\nTranscript: " . substr($result['data']['txt'] ?? '', 0, 500) . "...\n";
  }
  ?>
  ```

  ```go Go theme={null}
  package main

  import (
      "encoding/json"
      "fmt"
      "io"
      "net/http"
      "time"
  )

  func pollTranscriptionJob(apiKey, jobID string, maxWait, pollInterval time.Duration) (map[string]interface{}, error) {
      url := fmt.Sprintf("https://api.pictory.ai/pictoryapis/v1/jobs/%s", jobID)
      startTime := time.Now()

      for time.Since(startTime) < maxWait {
          req, _ := http.NewRequest("GET", url, nil)
          req.Header.Set("Authorization", apiKey)
          req.Header.Set("accept", "application/json")

          client := &http.Client{}
          resp, err := client.Do(req)
          if err != nil {
              return nil, err
          }

          body, _ := io.ReadAll(resp.Body)
          resp.Body.Close()

          var data map[string]interface{}
          json.Unmarshal(body, &data)

          success, _ := data["success"].(bool)
          if !success {
              fmt.Println("Job failed")
              return data, nil
          }

          jobData, _ := data["data"].(map[string]interface{})
          status, _ := jobData["status"].(string)

          if status == "in-progress" {
              elapsed := int(time.Since(startTime).Seconds())
              fmt.Printf("Transcription in progress... (%ds)\n", elapsed)
              time.Sleep(pollInterval)
              continue
          }

          // Job completed
          fmt.Println("Transcription complete!")
          return data, nil
      }

      return nil, fmt.Errorf("timeout waiting for transcription")
  }

  func main() {
      result, err := pollTranscriptionJob(
          "YOUR_API_KEY",
          "cbbc5305-3c1c-46f0-bdde-468e5ecd763f",
          10*time.Minute,
          15*time.Second,
      )
      if err != nil {
          fmt.Println("Error:", err)
          return
      }

      if success, ok := result["success"].(bool); ok && success {
          data := result["data"].(map[string]interface{})
          if txt, ok := data["txt"].(string); ok {
              if len(txt) > 500 {
                  txt = txt[:500] + "..."
              }
              fmt.Printf("\nTranscript: %s\n", txt)
          }
      }
  }
  ```
</CodeGroup>

***

## Understanding the Transcript Response

The completed transcription response includes several output formats:

| Field        | Description                                                                                                                                                 |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transcript` | Structured array of segments with word-level timing, speaker IDs, and pause markers. Suitable for building custom subtitle renderers or transcript editors. |
| `txt`        | Full transcript as plain text. Suitable for search indexing, summarization, or display.                                                                     |
| `srt`        | Transcript in SRT subtitle format. Can be saved directly as a `.srt` file for video players.                                                                |
| `vtt`        | Transcript in WebVTT format. Can be saved as a `.vtt` file for web-based video players.                                                                     |
| `mediaInfo`  | Source media metadata including duration, dimensions, and aspect ratio.                                                                                     |

### Pause Markers

The `transcript` array includes pause markers alongside spoken words. These entries are identified by the following characteristics:

* `is_pause` is set to `true`
* The `word` field contains an empty string
* `pause_size` indicates the duration category (e.g., `"small"`)

Pause markers are useful for understanding speech pacing and can be leveraged when building transcript-based editing workflows.

***

## Polling Best Practices

<Warning>
  Use a polling interval of **10–30 seconds** when checking job status. Polling too frequently may result in rate limiting.
</Warning>

1. **Use webhooks when possible.** Configure a `webhook` URL in the transcription request to receive automatic notification when the job completes, rather than polling.

2. **Implement timeouts.** Set a maximum wait time based on the expected file duration. Longer files require more processing time.

3. **Handle all states.** Verify both the `in-progress` status and the presence of transcript data in the response to determine completion.

4. **Cache results.** Once a transcription job completes, store the results locally. Completed job data may be cleaned after a retention period.
