# Start a Real-time STT agent (/en/api-reference/api-ref/speech-to-text/join)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Starts subtitle recording and translation.

- OpenAPI: /openapi/speech-to-text/v7.en.yaml
- Operation ID: join
- Method: POST
- Path: /api/speech-to-text/v1/projects/{appid}/join
- Endpoint: https://api.agora.io/api/speech-to-text/v1/projects/{appid}/join

## Servers

- https://api.agora.io

Use this method to start subtitle recording and subtitle translation.


## Authorization

This endpoint requires authentication.

- `BasicAuth`

## Parameters

- `appid` (path, required, string) - The App ID of the project.

## Request body

- `languages` (array, required) - The transcription languages you want to recognize. You can specify up to four languages. For a complete list, see [Supported languages](/en/realtime-media/speech-to-text/reference/supported-languages). Choosing multiple transcription languages can affect both quality and cost. For best practices, see [Optimize transcription quality and cost](/en/realtime-media/speech-to-text/build/extend-and-optimize/optimize-quality).
  - Max items: `4`
  - `languages.items` (string)
- `uidLanguagesConfig` (array) - Configure the transcription language for the specified user ID. Supports up to 5 configuration items.
  - Max items: `5`
  - `uidLanguagesConfig.items` (object) - Configure the transcription language for the specified user ID. Supports up to 5 configuration items.
    - `uidLanguagesConfig.items.uid` (string, required) - The ID of the user to be transcribed. You may configure a maximum of 5 uids for language recognition at the uid level.
    - `uidLanguagesConfig.items.languages` (array, required) - The transcription languages to recognize. Each uid can support a maximum of 4 languages. Refer to [Supported Languages](/en/realtime-media/speech-to-text/reference/supported-languages) for details.
      - Max items: `4`
      - `uidLanguagesConfig.items.languages.items` (string)
- `maxIdleTime` (integer) - Maximum channel idle time, in seconds. Value range: [0,259200]. Set `maxIdleTime` to `0` to disable automatic termination due to idle time. When the specified time is exceeded, the task ends automatically. Idle time means that there is no host in a live broadcast channel, or there is no user in a communication channel.

Independent of `maxIdleTime`, every task also has a maximum lifetime of 72 hours (259200 seconds). Once a task reaches this limit, Agora terminates it, even if `maxIdleTime` is `0`.
  - Default: `30`
  - Range: `[0, 259200]`
- `rtcConfig` (object, required) - Real-time subtitle configuration. After a user's voice is converted to text, the information is pushed to the channel as subtitles to match the UI real-time display.
  - `rtcConfig.channelName` (string, required) - The name of the channel to transcribe.
  - `rtcConfig.subBotUid` (string, deprecated) - The ID of the bot that subscribes to the audio stream. This is always identical to the value of the `pubBotUid`.
  - `rtcConfig.subBotToken` (string, deprecated) - The token used by the subscribing bot for channel authentication. Required only when your project has [App Certificate](/en/realtime-media/rtc/core-concepts#app-certificate) enabled. Generate this token on your token server. For details, see [Token authentication](/en/realtime-media/rtc/build/authenticate-users/deploy-token-server).
  - `rtcConfig.pubBotUid` (string, required) - The ID of the bot that pushes subtitle information to the channel. All UIDs within a channel must be unique. Ensure no other user or service bot is using this UID in the same channel.
  - `rtcConfig.pubBotToken` (string) - The token used by the subtitle-pushing bot for channel authentication. Required only when your project has [App Certificate](/en/realtime-media/rtc/core-concepts#app-certificate) enabled. Generate this token on your token server. For details, see [Token authentication](/en/realtime-media/rtc/build/authenticate-users/deploy-token-server).
  - `rtcConfig.subscribeAudioUids` (array) - The user IDs for the audio streams you want to subscribe. Set this parameter if you need to subscribe to the audio stream of certain users. Maximum array length: 32. You can set either `subscribeAudioUids` or `unSubscribeAudioUids`.
    - Max items: `32`
    - `rtcConfig.subscribeAudioUids.items` (string)
  - `rtcConfig.unSubscribeAudioUids` (array) - The user IDs for the audio streams you **do not** want to subscribe. Set this parameter if you don't need to subscribe to the audio stream of certain users. Maximum array length: 5. You can set either `subscribeAudioUids` or `unSubscribeAudioUids`.
    - Max items: `5`
    - `rtcConfig.unSubscribeAudioUids.items` (string)
  - `rtcConfig.cryptionMode` (integer, deprecated) - The encryption and decryption mode. When enabled, this mode is used for both decrypting incoming streams and encrypting outgoing subtitles.
- `0`: No encryption
- `1`: `AES_128_XTS` 128-bit AES encryption, XTS mode
- `2`: `AES_128_ECB` 128-bit AES encryption, ECB mode
- `3`: `AES_256_XTS` 256-bit AES encryption, XTS mode
- `4`: `SM4_128_ECB` 128-bit SM4 encryption, ECB mode
- `5`: `AES_128_GCM` 128-bit AES encryption, GCM mode
- `6`: `AES_256_GCM` 256-bit AES encryption, GCM mode
- `7`: `AES_128_GCM2` 128-bit AES encryption, GCM mode, Compared with `AES_128_GCM` encryption mode, this encryption mode is more secure and requires setting a key and salt.
- `8`: `AES_256_GCM2` 256-bit AES encryption, GCM mode, Compared with `AES_256_GCM` encryption mode, this encryption mode is more secure and requires setting a key and salt.
The decryption method must match the encryption method set for the channel.
    - Allowed: `0` | `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8`
  - `rtcConfig.secret` (string) - The encryption/decryption key. Required when `cryptionMode` is not `0`.
  - `rtcConfig.salt` (string) - A Base64-encoded, 32-byte encryption/decryption salt. Required only when `cryptionMode` is `7` or `8`.
  - `rtcConfig.enableJsonProtocol` (boolean) - Set the encoding format of the subtitle data pushed to the channel.
- `true`: Use JSON to push subtitles and compress data with gzip. Uses less bandwidth, but requires decoding.
- `false`: Use Protobuf to push subtitles (default). The data volume is smaller. Suitable for scenarios with high transmission efficiency requirements.

A single update can contain both a stabilized prefix segment and a segment that may still change. Both JSON and Protobuf formats can carry multiple segments in a single message. For details, see [Parse transcription data](/en/realtime-media/speech-to-text/build/process-transcription-data/parse-data).
- `translateConfig` (object) - Subtitle translation configuration.
  - `translateConfig.languages` (array) - The translation languages array. You can specify a maximum of 4 different source languages.

The translation language array. You can specify a maximum of 4 different source languages.


 Each array item is an object with:
    - Max items: `4`
    - `translateConfig.languages.items` (object) - Translation language pair configuration.
      - `translateConfig.languages.items.source` (string, required) - The source language for translation. Refer to [Supported Languages](/en/realtime-media/speech-to-text/reference/supported-languages#real-time-translation) for details.
      - `translateConfig.languages.items.target` (array, required) - The target languages for translation. You can configure up to 10 target languages for each source language. Refer to [Supported Languages](/en/realtime-media/speech-to-text/reference/supported-languages#real-time-translation) for details.
- **Single-language input**: If you set the source language to a single language, the target language must be different, otherwise an error is returned. For example, if you set the source language to English, you cannot set the target language to English.
- **Mixed-language input**: If you set the source language to mixed-language input, you can set the target language to one of the source languages. For example, if you set the source languages to Chinese and English, setting the target language to English translates both into English.
        - Max items: `10`
        - `translateConfig.languages.items.target.items` (string)
- `captionConfig` (object) - Subtitle recording configuration.
  - `captionConfig.sliceDuration` (integer) - The slice size of the recorded subtitle file, in seconds.
    - Default: `60`
    - Range: `[5, 28800]`
  - `captionConfig.storage` (object) - The configuration for third-party cloud storage.
    - `captionConfig.storage.accesskey` (string, required) - The access key of the third-party cloud storage.
    - `captionConfig.storage.secretkey` (string, required) - The secret key of the third-party cloud storage.
    - `captionConfig.storage.bucket` (string, required) - The bucket name of the third-party cloud storage.
    - `captionConfig.storage.vendor` (integer, required) - The third-party cloud storage platform:
- `1`: Amazon S3
- `2`: Alibaba Cloud
- `3`: Tencent Cloud
- `5`: Microsoft Azure
- `6`: Google Cloud
- `7`: Huawei Cloud
- `8`: Baidu Smart Cloud
- `11`: Other S3-compatible object storage systems, such as MinIO and self-hosted cloud storage systems
      - Allowed: `1` | `2` | `3` | `5` | `6` | `7` | `8` | `11`
    - `captionConfig.storage.region` (integer, required) - The region information for the third-party cloud storage. To ensure successful and real-time uploading of recorded files, the cloud storage region must match the region of the application server where you initiate the request. For example, if your App server is in East US, set the cloud storage region to East US as well. See [third-party storage regions](/en/realtime-media/cloud-recording/reference/region-vendor) for details.
    - `captionConfig.storage.fileNamePrefix` (array) - The storage location of the recorded file in the third-party cloud storage. The prefix length (including slashes) must not exceed 128 characters. The following characters are supported:
- Lowercase English letters (a-z)
- Uppercase English letters (A-Z)
- Numbers (0-9)
Symbols like slashes, underscores, and brackets must not appear in the string.
      - Max length: `128`
      - `captionConfig.storage.fileNamePrefix.items` (string)
- `extensionParams` (object) - Optional third-party cloud storage extension configuration. When `storage.vendor` is set to `11`, use this field to specify access information for standard S3-compatible object storage.
  - `extensionParams.endpoint` (string) - The access URL for the S3-compatible service, including the scheme. For example, `http://host:9002`. Required when `storage.vendor` is `11`.
  - `extensionParams.type` (string) - The rclone backend type. For standard S3, set this to `s3`.
    - Default: `s3`
  - `extensionParams.provider` (string) - The storage provider name. For example, `Minio` for MinIO.
  - `extensionParams.region` (string) - The rclone S3 backend region. If provided, this overrides the default region inferred from `storage.region`.
  - `extensionParams.tag` (string) - A base string for the object tag. Only effective when `storage.vendor` is Tencent Cloud, Alibaba Cloud, or Amazon S3.
  - `extensionParams.tagByRule` (array) - Appends key=value to the tag according to the filename rules. When both the tag and the filename exist, the rule takes precedence. Only applicable to Tencent Cloud, Alibaba Cloud, and Amazon S3.
    - `extensionParams.tagByRule.items` (object)
  - `extensionParams.sse` (string) - Server-side encryption method. `aes256` for AES-256 encryption, `kms` for AWS KMS. Only available for Amazon S3.
    - Allowed: `aes256` | `kms`
  - `extensionParams.overwritekeys` (object) - Maps the target object name using the uploaded file extension, used to override DstFileName.
- `keywords` (array) - Keyword list. Use it to improve the recognition accuracy of specific words during transcription. Supports up to 500 words.
  - Max items: `500`
  - `keywords.items` (string)
- `name` (string, required) - Unique ID of the agent. Maximum length is 64 characters. You cannot use the same ID repeatedly.
  - Max length: `64`

### Request body example

```json
{
  "languages": [
    "en-US"
  ],
  "keywords": [
    "Agora",
    "STT"
  ],
  "name": "agora-test",
  "maxIdleTime": 50,
  "rtcConfig": {
    "channelName": "agora-test",
    "pubBotUid": "88222"
  },
  "translateConfig": {
    "languages": [
      {
        "source": "en-US",
        "target": [
          "ar-SA",
          "id-ID",
          "fr-FR",
          "ja-JP"
        ]
      }
    ]
  },
  "captionConfig": {
    "sliceDuration": 60,
    "storage": {
      "accessKey": "test-oss",
      "secretKey": "test-oss",
      "bucket": "test-oss",
      "vendor": 2,
      "region": 3
    }
  }
}
```

## Request examples

### curl

```bash
curl --request POST \
  --url https://api.agora.io/api/speech-to-text/v1/projects/:appid/join \
  --header 'Authorization: Basic <credentials>' \
  --data '{
  "languages": [
    "en-US"
  ],
  "keywords": [
    "Agora",
    "STT"
  ],
  "name": "agora-test",
  "maxIdleTime": 50,
  "rtcConfig": {
    "channelName": "agora-test",
    "pubBotUid": "88222"
  },
  "translateConfig": {
    "languages": [
      {
        "source": "en-US",
        "target": [
          "ar-SA",
          "id-ID",
          "fr-FR",
          "ja-JP"
        ]
      }
    ]
  },
  "captionConfig": {
    "sliceDuration": 60,
    "storage": {
      "accessKey": "test-oss",
      "secretKey": "test-oss",
      "bucket": "test-oss",
      "vendor": 2,
      "region": 3
    }
  }
}'
```

### Python

```python
import requests

url = "https://api.agora.io/api/speech-to-text/v1/projects/:appid/join"

payload = {
    "languages": ["en-US"],
    "keywords": ["Agora","STT"],
    "name": "agora-test",
    "maxIdleTime": 50,
    "rtcConfig": {
        "channelName": "agora-test",
        "pubBotUid": "88222"
    },
    "translateConfig": {
        "languages": [
            {
                "source": "en-US",
                "target": ["ar-SA", "id-ID", "fr-FR", "ja-JP"]
            }
        ]
    },
    "captionConfig": {
        "sliceDuration": 60,
        "storage": {
            "accessKey": "test-oss",
            "secretKey": "test-oss",
            "bucket": "test-oss",
            "vendor": 2,
            "region": 3
        }
    }
}
headers = {"Authorization": "Basic <credentials>"}

response = requests.request("POST", url, json=payload, headers=headers)

print(response.text)
```

### Node.js

```javascript
const url = 'https://api.agora.io/api/speech-to-text/v1/projects/:appid/join';
const options = {
  method: 'POST',
  headers: {Authorization: 'Basic <credentials>'},
  body: JSON.stringify({
    languages: ['en-US'],
    keywords: ['Agora','STT'],
    name: 'agora-test',
    maxIdleTime: 50,
    rtcConfig: {channelName: 'agora-test', pubBotUid: '88222'},
    translateConfig: {
      languages: [{source: 'en-US', target: ['ar-SA', 'id-ID', 'fr-FR', 'ja-JP']}]
    },
    captionConfig: {
      sliceDuration: 60,
      storage: {
        accessKey: 'test-oss',
        secretKey: 'test-oss',
        bucket: 'test-oss',
        vendor: 2,
        region: 3
      }
    }
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```


### Response

- If the returned status code is `200`, the request was successful. The response body contains the result of the request.


## Responses

### 200

OK

- `agent_id` (string) - The ID of the agent.
- `create_ts` (integer) - The Unix timestamp (in seconds) when the agent was created.
- `status` (string) - The current status of the agent:
- `IDLE`: The agent is not initialized
- `STARTING`: The agent is starting
- `RUNNING`: The agent is running
- `STOPPING`: The agent is exiting
- `STOPPED`: The agent exited successfully
- `RECOVERING`: The agent is recovering
- `FAILED`: Agent exit failed
  - Allowed: `IDLE` | `STARTING` | `RUNNING` | `STOPPING` | `STOPPED` | `RECOVERING` | `FAILED`
### default

Error response.

- `detail` (string) - Details of the request failure.
- `reason` (string) - The reason why the request failed.

### Response

Refer to the detail and reason fields to understand the possible reasons for failure.


## Response examples

### 200

```json
{
  "agent_id": "Agent ID.",
  "create_ts": null,
  "status": "RUNNING"
}
```
### default

```json
{
  "detail": "Details of the request failure.",
  "reason": "The reason why the request failed."
}
```
