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

# Extract Dialogue Data with LLM Gateway and JSON

In this guide, we'll show you how to use AssemblyAI's [LLM Gateway](/llm-gateway) framework to process several audio files, and then format your results in JSON (JavaScript Object Notation) format.

JSON allows you to programmatically format, parse, and transfer responses from LLM Gateway, which is useful for implementing LLM Gateway with a wide range of other applications.

In this example, we will leverage the JSON formatting to create a .csv file from a directory of files that must be transcribed and submitted to LLM Gateway. However, you can use the same concepts in this guide to generate a JSON-formatted response, which you can then use to update a database table or interact with other APIs.

## Quickstart

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ````python expandable theme={null}
    import requests
    import json
    import os
    import csv
    import time
    import re

    # Configuration
    api_key = "<YOUR_API_KEY>"
    base_url = "https://api.assemblyai.com"
    headers = {"authorization": api_key}
    output_filename = "profiles.csv"

    def extract_json(text):
        """Extract JSON from text that might contain markdown or extra text"""
        # First, try to remove markdown code blocks
        text = text.strip()

        # Remove ```json and ``` markers
        if text.startswith("```"):
            text = re.sub(r'^```(?:json)?\s*', '', text)
            text = re.sub(r'\s*```$', '', text)

        # Find the first { and last } to extract just the JSON object
        first_brace = text.find('{')
        last_brace = text.rfind('}')

        if first_brace != -1 and last_brace != -1:
            json_str = text[first_brace:last_brace + 1]
            return json.loads(json_str)

        # If that didn't work, try parsing the whole thing
        return json.loads(text)

    def upload_file(file_path):
        """Upload a local audio file to AssemblyAI"""
        with open(file_path, "rb") as f:
            response = requests.post(f"{base_url}/v2/upload", headers=headers, data=f)
            if response.status_code != 200:
                print(f"Error uploading {file_path}: {response.status_code}, {response.text}")
                response.raise_for_status()
            return response.json()["upload_url"]

    def transcribe_audio(audio_url):
        """Submit audio for transcription and poll until complete"""
        # Submit transcription request
        data = {"audio_url": audio_url}
        response = requests.post(f"{base_url}/v2/transcript", headers=headers, json=data)

        if response.status_code != 200:
            print(f"Error submitting transcription: {response.status_code}, {response.text}")
            response.raise_for_status()

        transcript_id = response.json()["id"]
        polling_endpoint = f"{base_url}/v2/transcript/{transcript_id}"

        # Poll for completion
        while True:
            transcript = requests.get(polling_endpoint, headers=headers).json()
            if transcript["status"] == "completed":
                return transcript_id
            elif transcript["status"] == "error":
                raise RuntimeError(f"Transcription failed: {transcript['error']}")
            else:
                time.sleep(3)

    def process_with_llm_gateway(transcript_id, prompt):
        """Send transcript to LLM Gateway for processing"""
        llm_gateway_data = {
            "model": "claude-sonnet-4-6",
            "messages": [
                {
                    "role": "user",
                    "content": f"{prompt}\n\n{{{{ transcript }}}}"
                }
            ],
            "transcript_id": transcript_id,
            "max_tokens": 1500
        }

        response = requests.post(
            "https://llm-gateway.assemblyai.com/v1/chat/completions",
            headers=headers,
            json=llm_gateway_data
        )

        result = response.json()

        if "error" in result:
            raise RuntimeError(f"LLM Gateway error: {result['error']}")

        return result['choices'][0]['message']['content']

    # Main execution
    prompt = """
            You are an HR executive scanning through an interview transcript to extract information about a candidate.
            You are required to create a JSON response with key information about the candidate.
            You will use this template for your answer:
            {
                "Name": "<candidate-name>",
                "Position": "<job position that candidate is applying for>",
                "Past experience": "<A short phrase describing the candidate's relevant past experience for the role>"
            }
            Do not include any other text in your response. Only respond in JSON format that is not surrounded by markdown code, as your response will be parsed programmatically as JSON.
            """

    # Get all files from interviews directory
    interview_files = [os.path.join("interviews", file) for file in os.listdir("interviews")]

    with open(output_filename, "w", newline="") as file:
        writer = csv.writer(file)
        header = ["Name", "Position", "Past Experience"]
        writer.writerow(header)

        print(f"Processing {len(interview_files)} interview files...")

        for interview_file in interview_files:
            print(f"\nProcessing: {interview_file}")

            # Upload file and get URL
            print("  Uploading file...")
            audio_url = upload_file(interview_file)

            # Transcribe audio
            print("  Transcribing...")
            transcript_id = transcribe_audio(audio_url)

            # Process with LLM Gateway
            print("  Analyzing with LLM Gateway...")
            llm_response = process_with_llm_gateway(transcript_id, prompt)

            # Parse JSON response
            interviewee_data = extract_json(llm_response)
            writer.writerow(interviewee_data.values())
            print(f"  Completed: {interviewee_data['Name']}")

    print(f"\nCreated .csv file {output_filename}")
    ````
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ````javascript expandable theme={null}
    import { readdirSync } from "fs";
    import fs from "fs";
    import path from "path";

    // Configuration
    const apiKey = "<YOUR_API_KEY>";
    const baseUrl = "https://api.assemblyai.com";
    const headers = { authorization: apiKey };
    const outputFilename = "profiles.csv";

    function extractJson(text) {
      // Extract JSON from text that might contain markdown or extra text
      text = text.trim();

      // Remove ```json and ``` markers
      if (text.startsWith("```")) {
        text = text.replace(/^```(?:json)?\s*/g, "");
        text = text.replace(/\s*```$/g, "");
      }

      // Find the first { and last } to extract just the JSON object
      const firstBrace = text.indexOf("{");
      const lastBrace = text.lastIndexOf("}");

      if (firstBrace !== -1 && lastBrace !== -1) {
        const jsonStr = text.slice(firstBrace, lastBrace + 1);
        return JSON.parse(jsonStr);
      }

      // If that didn't work, try parsing the whole thing
      return JSON.parse(text);
    }

    async function uploadFile(filePath) {
      // Upload a local audio file to AssemblyAI
      const fileData = await fs.promises.readFile(filePath);
      const res = await fetch(`${baseUrl}/v2/upload`, {
        method: "POST",
        headers,
        body: fileData,
      });
      if (!res.ok) {
        throw new Error(`Error uploading ${filePath}: ${res.status}`);
      }
      const response = await res.json();
      return response.upload_url;
    }

    async function transcribeAudio(audioUrl) {
      // Submit audio for transcription and poll until complete
      const data = { audio_url: audioUrl };
      const res = await fetch(`${baseUrl}/v2/transcript`, {
        method: "POST",
        headers: { ...headers, "Content-Type": "application/json" },
        body: JSON.stringify(data),
      });

      if (!res.ok) {
        throw new Error(`Error submitting transcription: ${res.status}`);
      }

      const response = await res.json();
      const transcriptId = response.id;
      const pollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}`;

      // Poll for completion
      while (true) {
        const res = await fetch(pollingEndpoint, { headers });
        if (!res.ok) throw new Error(`Error: ${res.status}`);
        const transcript = await res.json();
        if (transcript.status === "completed") {
          return transcriptId;
        } else if (transcript.status === "error") {
          throw new Error(`Transcription failed: ${transcript.error}`);
        } else {
          await new Promise((resolve) => setTimeout(resolve, 3000));
        }
      }
    }

    async function processWithLlmGateway(transcriptId, prompt) {
      // Send transcript to LLM Gateway for processing
      const llmGatewayData = {
        model: "claude-sonnet-4-6",
        messages: [
          {
            role: "user",
            content: `${prompt}\n\n{{ transcript }}`,
          },
        ],
        transcript_id: transcriptId,
        max_tokens: 1500,
      };

      const res = await fetch("https://llm-gateway.assemblyai.com/v1/chat/completions", {
        method: "POST",
        headers: { ...headers, "Content-Type": "application/json" },
        body: JSON.stringify(llmGatewayData),
      });
      if (!res.ok) throw new Error(`Error: ${res.status}`);
      const response = await res.json();

      if (response.error) {
        throw new Error(`LLM Gateway error: ${response.error}`);
      }

      return response.choices[0].message.content;
    }

    // Main execution
    const prompt = `
            You are an HR executive scanning through an interview transcript to extract information about a candidate.
            You are required to create a JSON response with key information about the candidate.
            You will use this template for your answer:
            {
                "Name": "<candidate-name>",
                "Position": "<job position that candidate is applying for>",
                "Past experience": "<A short phrase describing the candidate's relevant past experience for the role>"
            }
            Do not include any other text in your response. Only respond in JSON format that is not surrounded by markdown code, as your response will be parsed programmatically as JSON.
            `;

    // Get all files from interviews directory
    const interviewFiles = readdirSync("interviews").map((file) =>
      path.join("interviews", file)
    );

    const header = ["Name", "Position", "Past Experience"];
    const csvRows = [header.join(",")];

    console.log(`Processing ${interviewFiles.length} interview files...`);

    for (const interviewFile of interviewFiles) {
      console.log(`\nProcessing: ${interviewFile}`);

      // Upload file and get URL
      console.log("  Uploading file...");
      const audioUrl = await uploadFile(interviewFile);

      // Transcribe audio
      console.log("  Transcribing...");
      const transcriptId = await transcribeAudio(audioUrl);

      // Process with LLM Gateway
      console.log("  Analyzing with LLM Gateway...");
      const llmResponse = await processWithLlmGateway(transcriptId, prompt);

      // Parse JSON response
      const intervieweeData = extractJson(llmResponse);
      csvRows.push(Object.values(intervieweeData).join(","));
      console.log(`  Completed: ${intervieweeData["Name"]}`);
    }

    fs.writeFileSync(outputFilename, csvRows.join("\n"));
    console.log(`\nCreated .csv file ${outputFilename}`);
    ````
  </Tab>
</Tabs>

## Get Started

Before we begin, make sure you have an AssemblyAI account and an API key. You can [sign up for an AssemblyAI account](https://www.assemblyai.com/dashboard/home) and get your API key from your dashboard.

## Step-by-Step Instructions

In this guide, we will ask the same questions to LLM Gateway about multiple files. Then, we will collate the answers in a .csv file.

Install the required packages:

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```bash theme={null}
    pip install requests
    ```
  </Tab>
</Tabs>

Import the necessary libraries for making an HTTP request and set your API key, headers, and base URL.

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```python theme={null}
    import requests
    import json
    import os
    import csv
    import time
    import re

    # Configuration
    api_key = "<YOUR_API_KEY>"
    base_url = "https://api.assemblyai.com"
    headers = {"authorization": api_key}
    output_filename = "profiles.csv"
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript theme={null}
    import { readdirSync } from "fs";
    import fs from "fs";
    import path from "path";

    // Configuration
    const apiKey = "<YOUR_API_KEY>";
    const baseUrl = "https://api.assemblyai.com";
    const headers = { authorization: apiKey };
    const outputFilename = "profiles.csv";
    ```
  </Tab>
</Tabs>

Define a function to extract the JSON text from the response from LLM Gateway.

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ````python theme={null}
    def extract_json(text):
        """Extract JSON from text that might contain markdown or extra text"""
        # First, try to remove markdown code blocks
        text = text.strip()

        # Remove ```json and ``` markers
        if text.startswith("```"):
            text = re.sub(r'^```(?:json)?\s*', '', text)
            text = re.sub(r'\s*```$', '', text)

        # Find the first { and last } to extract just the JSON object
        first_brace = text.find('{')
        last_brace = text.rfind('}')

        if first_brace != -1 and last_brace != -1:
            json_str = text[first_brace:last_brace + 1]
            return json.loads(json_str)

        # If that didn't work, try parsing the whole thing
        return json.loads(text)
    ````
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ````javascript expandable theme={null}
    function extractJson(text) {
      // Extract JSON from text that might contain markdown or extra text
      text = text.trim();

      // Remove ```json and ``` markers
      if (text.startsWith("```")) {
        text = text.replace(/^```(?:json)?\s*/g, "");
        text = text.replace(/\s*```$/g, "");
      }

      // Find the first { and last } to extract just the JSON object
      const firstBrace = text.indexOf("{");
      const lastBrace = text.lastIndexOf("}");

      if (firstBrace !== -1 && lastBrace !== -1) {
        const jsonStr = text.slice(firstBrace, lastBrace + 1);
        return JSON.parse(jsonStr);
      }

      // If that didn't work, try parsing the whole thing
      return JSON.parse(text);
    }
    ````
  </Tab>
</Tabs>

Define functions to upload and transcribe each file using AssemblyAI's Async API.

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```python expandable theme={null}
    def upload_file(file_path):
        """Upload a local audio file to AssemblyAI"""
        with open(file_path, "rb") as f:
            response = requests.post(f"{base_url}/v2/upload", headers=headers, data=f)
            if response.status_code != 200:
                print(f"Error uploading {file_path}: {response.status_code}, {response.text}")
                response.raise_for_status()
            return response.json()["upload_url"]

    def transcribe_audio(audio_url):
        """Submit audio for transcription and poll until complete"""
        # Submit transcription request
        data = {"audio_url": audio_url}
        response = requests.post(f"{base_url}/v2/transcript", headers=headers, json=data)

        if response.status_code != 200:
            print(f"Error submitting transcription: {response.status_code}, {response.text}")
            response.raise_for_status()

        transcript_id = response.json()["id"]
        polling_endpoint = f"{base_url}/v2/transcript/{transcript_id}"

        # Poll for completion
        while True:
            transcript = requests.get(polling_endpoint, headers=headers).json()
            if transcript["status"] == "completed":
                return transcript_id
            elif transcript["status"] == "error":
                raise RuntimeError(f"Transcription failed: {transcript['error']}")
            else:
                time.sleep(3)
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript expandable theme={null}
    async function uploadFile(filePath) {
      // Upload a local audio file to AssemblyAI
      const fileData = await fs.promises.readFile(filePath);
      const res = await fetch(`${baseUrl}/v2/upload`, {
        method: "POST",
        headers,
        body: fileData,
      });
      if (!res.ok) {
        throw new Error(`Error uploading ${filePath}: ${res.status}`);
      }
      const response = await res.json();
      return response.upload_url;
    }

    async function transcribeAudio(audioUrl) {
      // Submit audio for transcription and poll until complete
      const data = { audio_url: audioUrl };
      const res = await fetch(`${baseUrl}/v2/transcript`, {
        method: "POST",
        headers: { ...headers, "Content-Type": "application/json" },
        body: JSON.stringify(data),
      });

      if (!res.ok) {
        throw new Error(`Error submitting transcription: ${res.status}`);
      }

      const response = await res.json();
      const transcriptId = response.id;
      const pollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}`;

      // Poll for completion
      while (true) {
        const res = await fetch(pollingEndpoint, { headers });
        if (!res.ok) throw new Error(`Error: ${res.status}`);
        const transcript = await res.json();
        if (transcript.status === "completed") {
          return transcriptId;
        } else if (transcript.status === "error") {
          throw new Error(`Transcription failed: ${transcript.error}`);
        } else {
          await new Promise((resolve) => setTimeout(resolve, 3000));
        }
      }
    }
    ```
  </Tab>
</Tabs>

Define a function to process each transcript text with LLM Gateway.

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```python expandable theme={null}
    def process_with_llm_gateway(transcript_id, prompt):
        """Send transcript to LLM Gateway for processing"""
        llm_gateway_data = {
            "model": "claude-sonnet-4-6",
            "messages": [
                {
                    "role": "user",
                    "content": f"{prompt}\n\n{{{{ transcript }}}}"
                }
            ],
            "transcript_id": transcript_id,
            "max_tokens": 1500
        }

        response = requests.post(
            "https://llm-gateway.assemblyai.com/v1/chat/completions",
            headers=headers,
            json=llm_gateway_data
        )

        result = response.json()

        if "error" in result:
            raise RuntimeError(f"LLM Gateway error: {result['error']}")

        return result['choices'][0]['message']['content']
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript expandable theme={null}
    async function processWithLlmGateway(transcriptId, prompt) {
      // Send transcript to LLM Gateway for processing
      const llmGatewayData = {
        model: "claude-sonnet-4-6",
        messages: [
          {
            role: "user",
            content: `${prompt}\n\n{{ transcript }}`,
          },
        ],
        transcript_id: transcriptId,
        max_tokens: 1500,
      };

      const res = await fetch("https://llm-gateway.assemblyai.com/v1/chat/completions", {
        method: "POST",
        headers: { ...headers, "Content-Type": "application/json" },
        body: JSON.stringify(llmGatewayData),
      });
      if (!res.ok) throw new Error(`Error: ${res.status}`);
      const response = await res.json();

      if (response.error) {
        throw new Error(`LLM Gateway error: ${response.error}`);
      }

      return response.choices[0].message.content;
    }
    ```
  </Tab>
</Tabs>

Define your LLM Gateway request prompt.

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```python theme={null}
    prompt = """
            You are an HR executive scanning through an interview transcript to extract information about a candidate.
            You are required to create a JSON response with key information about the candidate.
            You will use this template for your answer:
            {
                "Name": "<candidate-name>",
                "Position": "<job position that candidate is applying for>",
                "Past experience": "<A short phrase describing the candidate's relevant past experience for the role>"
            }
            Do not include any other text in your response. Only respond in JSON format that is not surrounded by markdown code, as your response will be parsed programmatically as JSON.
            """
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript theme={null}
    const prompt = `
            You are an HR executive scanning through an interview transcript to extract information about a candidate.
            You are required to create a JSON response with key information about the candidate.
            You will use this template for your answer:
            {
                "Name": "<candidate-name>",
                "Position": "<job position that candidate is applying for>",
                "Past experience": "<A short phrase describing the candidate's relevant past experience for the role>"
            }
            Do not include any other text in your response. Only respond in JSON format that is not surrounded by markdown code, as your response will be parsed programmatically as JSON.
            `;
    ```
  </Tab>
</Tabs>

Retrieve and process each file in the `interviews` folder and create a .csv file with the results.

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```python expandable theme={null}
    interview_files = [os.path.join("interviews", file) for file in os.listdir("interviews")]

    with open(output_filename, "w", newline="") as file:
        writer = csv.writer(file)
        header = ["Name", "Position", "Past Experience"]
        writer.writerow(header)

        print(f"Processing {len(interview_files)} interview files...")

        for interview_file in interview_files:
            print(f"\nProcessing: {interview_file}")

            # Upload file and get URL
            print("  Uploading file...")
            audio_url = upload_file(interview_file)

            # Transcribe audio
            print("  Transcribing...")
            transcript_id = transcribe_audio(audio_url)

            # Process with LLM Gateway
            print("  Analyzing with LLM Gateway...")
            llm_response = process_with_llm_gateway(transcript_id, prompt)

            # Parse JSON response
            interviewee_data = extract_json(llm_response)
            writer.writerow(interviewee_data.values())
            print(f"  Completed: {interviewee_data['Name']}")

    print(f"\nCreated .csv file {output_filename}")
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript expandable theme={null}
    // Get all files from interviews directory
    const interviewFiles = readdirSync("interviews").map((file) =>
      path.join("interviews", file)
    );

    const header = ["Name", "Position", "Past Experience"];
    const csvRows = [header.join(",")];

    console.log(`Processing ${interviewFiles.length} interview files...`);

    for (const interviewFile of interviewFiles) {
      console.log(`\nProcessing: ${interviewFile}`);

      // Upload file and get URL
      console.log("  Uploading file...");
      const audioUrl = await uploadFile(interviewFile);

      // Transcribe audio
      console.log("  Transcribing...");
      const transcriptId = await transcribeAudio(audioUrl);

      // Process with LLM Gateway
      console.log("  Analyzing with LLM Gateway...");
      const llmResponse = await processWithLlmGateway(transcriptId, prompt);

      // Parse JSON response
      const intervieweeData = extractJson(llmResponse);
      csvRows.push(Object.values(intervieweeData).join(","));
      console.log(`  Completed: ${intervieweeData["Name"]}`);
    }

    fs.writeFileSync(outputFilename, csvRows.join("\n"));
    console.log(`\nCreated .csv file ${outputFilename}`);
    ```
  </Tab>
</Tabs>

For context, this is the response from LLM Gateway with our prompt.

```json theme={null}
{
  "Name": "John Smith",
  "Position": "software engineer",
  "Past experience": "three years of experience at Google"
}
```

You can now run your Python script and you should see that a `profiles.csv` file is generated.
