> ## 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.

# Custom Topic Tags Using LLM Gateway

In this guide we will show you how to label content with custom topic tags using AssemblyAI's LLM Gateway.

## Quickstart

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

    base_url = "https://api.assemblyai.com"
    headers = {"authorization": "<YOUR_API_KEY>"}

    # Step 1: Transcribe the audio
    audio_url = "https://storage.googleapis.com/aai-web-samples/meeting.mp4"
    data = {"audio_url": audio_url, "speech_models": ["universal-3-pro"]}

    response = requests.post(base_url + "/v2/transcript", json=data, headers=headers)
    transcript_id = response.json()['id']
    polling_endpoint = base_url + "/v2/transcript/" + transcript_id

    while True:
        transcription_result = requests.get(polling_endpoint, headers=headers).json()
        if transcription_result['status'] == 'completed':
            break
        elif transcription_result['status'] == 'error':
            raise RuntimeError(f"Transcription failed: {transcription_result['error']}")
        else:
            time.sleep(3)

    # Step 2: Generate topic tags with LLM Gateway
    tag_list = {
        'Sports': 'News and updates on various athletic events, teams, and sports personalities.',
        'Politics': 'Coverage and discussion of government activities, policies, and political events.',
        'Entertainment': 'Information on movies, music, television, celebrities, and arts.',
        'Technology': 'News and reviews on gadgets, software, tech advancements, and trends.',
        'Health': 'Articles focusing on medical news, wellness, and health-related topics.',
        'Business': 'Updates on markets, industries, companies, and economic trends.',
        'Science': 'News and insights into scientific discoveries, research, and innovations.',
        'Education': 'Coverage of topics related to schools, educational policies, and learning.',
        'Travel': 'Information on destinations, travel tips, and tourism news.',
        'Lifestyle': 'Articles on fashion, hobbies, personal interests, and daily life.',
        'Environment': 'News and discussion about environmental issues and sustainability.',
        'Finance': 'Information on personal finance, investments, banking, and economic news.',
        'World News': 'International news covering global events and issues.',
        'Crime': 'Reports and updates on criminal activities, law enforcement, and legal cases.',
        'Culture': 'Coverage of cultural events, traditions, and societal norms.'
    }

    prompt = f"""
    You are a helpful assistant designed to label video content with topic tags.

    I will give you a list of topics and definitions. Select the most relevant topic from the list. Return your selection and nothing else.

    <topics_list>
    {tag_list}
    </topics_list>
    """

    llm_gateway_data = {
        "model": "claude-sonnet-4-5-20250929",
        "messages": [
            {"role": "user", "content": f"{prompt}\n\n{{{{ transcript }}}}"}
        ],
        "transcript_id": transcript_id,
        "max_tokens": 500
    }

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

    result = response.json()["choices"][0]["message"]["content"]
    print(result.strip())
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript expandable theme={null}
    const baseUrl = "https://api.assemblyai.com";
    const headers = { authorization: "<YOUR_API_KEY>" };

    // Step 1: Transcribe the audio
    const audioUrl = "https://storage.googleapis.com/aai-web-samples/meeting.mp4";
    const data = { audio_url: audioUrl, speech_models: ["universal-3-pro"] };

    let 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: ${res.status}`);
    const transcriptResponse = await res.json();
    const transcriptId = transcriptResponse.id;
    const pollingEndpoint = baseUrl + "/v2/transcript/" + transcriptId;

    let transcriptionResult;
    while (true) {
        res = await fetch(pollingEndpoint, { headers });
        if (!res.ok) throw new Error(`Error: ${res.status}`);
        transcriptionResult = await res.json();
        if (transcriptionResult.status === "completed") {
            break;
        } else if (transcriptionResult.status === "error") {
            throw new Error(`Transcription failed: ${transcriptionResult.error}`);
        } else {
            await new Promise((resolve) => setTimeout(resolve, 3000));
        }
    }

    // Step 2: Generate topic tags with LLM Gateway
    const tagList = {
        Sports: "News and updates on various athletic events, teams, and sports personalities.",
        Politics: "Coverage and discussion of government activities, policies, and political events.",
        Entertainment: "Information on movies, music, television, celebrities, and arts.",
        Technology: "News and reviews on gadgets, software, tech advancements, and trends.",
        Health: "Articles focusing on medical news, wellness, and health-related topics.",
        Business: "Updates on markets, industries, companies, and economic trends.",
        Science: "News and insights into scientific discoveries, research, and innovations.",
        Education: "Coverage of topics related to schools, educational policies, and learning.",
        Travel: "Information on destinations, travel tips, and tourism news.",
        Lifestyle: "Articles on fashion, hobbies, personal interests, and daily life.",
        Environment: "News and discussion about environmental issues and sustainability.",
        Finance: "Information on personal finance, investments, banking, and economic news.",
        "World News": "International news covering global events and issues.",
        Crime: "Reports and updates on criminal activities, law enforcement, and legal cases.",
        Culture: "Coverage of cultural events, traditions, and societal norms.",
    };

    const prompt = `
    You are a helpful assistant designed to label video content with topic tags.

    I will give you a list of topics and definitions. Select the most relevant topic from the list. Return your selection and nothing else.

    <topics_list>
    ${JSON.stringify(tagList, null, 2)}
    </topics_list>
    `;

    const llmGatewayData = {
        model: "claude-sonnet-4-5-20250929",
        messages: [
            { role: "user", content: `${prompt}\n\n{{ transcript }}` },
        ],
        transcript_id: transcriptId,
        max_tokens: 500,
    };

    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();

    const result = response.choices[0].message.content;
    console.log(result.trim());
    ```
  </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/app) and get your API key from your dashboard.

## Step-by-Step Instructions

### Install dependencies

Install the required packages:

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

Set up your API client and transcribe the audio file:

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

    base_url = "https://api.assemblyai.com"
    headers = {"authorization": "<YOUR_API_KEY>"}

    # Transcribe the audio
    audio_url = "https://storage.googleapis.com/aai-web-samples/meeting.mp4"
    data = {"audio_url": audio_url, "speech_models": ["universal-3-pro"]}  # You can also use a URL to an audio or video file on the web

    response = requests.post(base_url + "/v2/transcript", json=data, headers=headers)
    transcript_id = response.json()['id']
    polling_endpoint = base_url + "/v2/transcript/" + transcript_id

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

  <Tab language="javascript" title="JavaScript">
    ```javascript expandable theme={null}
    const baseUrl = "https://api.assemblyai.com";
    const headers = { authorization: "<YOUR_API_KEY>" };

    // Transcribe the audio
    const audioUrl = "https://storage.googleapis.com/aai-web-samples/meeting.mp4"; // You can also use a URL to an audio or video file on the web
    const data = { audio_url: audioUrl, speech_models: ["universal-3-pro"] };

    let 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: ${res.status}`);
    const transcriptResponse = await res.json();
    const transcriptId = transcriptResponse.id;
    const pollingEndpoint = baseUrl + "/v2/transcript/" + transcriptId;

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

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    Create a `tag_list` of custom topics, which consists of a key that is the topic and a value that is a short description of what qualifies a file to be labeled with that topic.

    Here is an example of a `tag_list` that can be used for videos or podcasts:

    ```python theme={null}
    tag_list = {
        'Sports': 'News and updates on various athletic events, teams, and sports personalities.',
        'Politics': 'Coverage and discussion of government activities, policies, and political events.',
        'Entertainment': 'Information on movies, music, television, celebrities, and arts.',
        'Technology': 'News and reviews on gadgets, software, tech advancements, and trends.',
        'Health': 'Articles focusing on medical news, wellness, and health-related topics.',
        'Business': 'Updates on markets, industries, companies, and economic trends.',
        'Science': 'News and insights into scientific discoveries, research, and innovations.',
        'Education': 'Coverage of topics related to schools, educational policies, and learning.',
        'Travel': 'Information on destinations, travel tips, and tourism news.',
        'Lifestyle': 'Articles on fashion, hobbies, personal interests, and daily life.',
        'Environment': 'News and discussion about environmental issues and sustainability.',
        'Finance': 'Information on personal finance, investments, banking, and economic news.',
        'World News': 'International news covering global events and issues.',
        'Crime': 'Reports and updates on criminal activities, law enforcement, and legal cases.',
        'Culture': 'Coverage of cultural events, traditions, and societal norms.'
    }
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    Create a `tagList` of custom topics, which consists of a key that is the topic and a value that is a short description of what qualifies a file to be labeled with that topic.

    Here is an example of a `tagList` that can be used for videos or podcasts:

    ```javascript theme={null}
    const tagList = {
        Sports: "News and updates on various athletic events, teams, and sports personalities.",
        Politics: "Coverage and discussion of government activities, policies, and political events.",
        Entertainment: "Information on movies, music, television, celebrities, and arts.",
        Technology: "News and reviews on gadgets, software, tech advancements, and trends.",
        Health: "Articles focusing on medical news, wellness, and health-related topics.",
        Business: "Updates on markets, industries, companies, and economic trends.",
        Science: "News and insights into scientific discoveries, research, and innovations.",
        Education: "Coverage of topics related to schools, educational policies, and learning.",
        Travel: "Information on destinations, travel tips, and tourism news.",
        Lifestyle: "Articles on fashion, hobbies, personal interests, and daily life.",
        Environment: "News and discussion about environmental issues and sustainability.",
        Finance: "Information on personal finance, investments, banking, and economic news.",
        "World News": "International news covering global events and issues.",
        Crime: "Reports and updates on criminal activities, law enforcement, and legal cases.",
        Culture: "Coverage of cultural events, traditions, and societal norms.",
    };
    ```
  </Tab>
</Tabs>

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    Here is another example of a `tag_list` that can be used for support calls:

    ```python theme={null}
    tag_list = {
        'Account Issues': 'Problems related to user accounts, such as login difficulties or account access.',
        'Technical Support': 'Inquiries regarding software or hardware functionality and troubleshooting.',
        'Billing and Payments': 'Questions or problems about invoices, payments, or subscription plans.',
        'Product Inquiry': 'Requests for information about product features, capabilities, or availability.',
        'Service Disruption': 'Reports of outages or interruptions in service performance or availability.'
    }
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    Here is another example of a `tagList` that can be used for support calls:

    ```javascript theme={null}
    const tagList = {
        "Account Issues": "Problems related to user accounts, such as login difficulties or account access.",
        "Technical Support": "Inquiries regarding software or hardware functionality and troubleshooting.",
        "Billing and Payments": "Questions or problems about invoices, payments, or subscription plans.",
        "Product Inquiry": "Requests for information about product features, capabilities, or availability.",
        "Service Disruption": "Reports of outages or interruptions in service performance or availability.",
    };
    ```
  </Tab>
</Tabs>

Use LLM Gateway to analyze the transcript and select the most relevant topic tag. This is an example prompt, which you can modify to suit your specific requirements.

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```python expandable theme={null}
    prompt = f"""
    You are a helpful assistant designed to label video content with topic tags.

    I will give you a list of topics and definitions. Select the most relevant topic from the list. Return your selection and nothing else.

    <topics_list>
    {tag_list}
    </topics_list>
    """

    llm_gateway_data = {
        "model": "claude-sonnet-4-5-20250929",
        "messages": [
            {"role": "user", "content": f"{prompt}\n\n{{{{ transcript }}}}"}
        ],
        "transcript_id": transcript_id,
        "max_tokens": 500
    }

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

    result = response.json()["choices"][0]["message"]["content"]
    print(result.strip())
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript expandable theme={null}
    const prompt = `
    You are a helpful assistant designed to label video content with topic tags.

    I will give you a list of topics and definitions. Select the most relevant topic from the list. Return your selection and nothing else.

    <topics_list>
    ${JSON.stringify(tagList, null, 2)}
    </topics_list>
    `;

    const llmGatewayData = {
        model: "claude-sonnet-4-5-20250929",
        messages: [
            { role: "user", content: `${prompt}\n\n{{ transcript }}` },
        ],
        transcript_id: transcriptId,
        max_tokens: 500,
    };

    let 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();

    const result = response.choices[0].message.content;
    console.log(result.trim());
    ```
  </Tab>
</Tabs>
