> For clean Markdown of any page, append `.md` to the page URL.
> For a complete documentation index, see https://docs.sarvam.ai/llms.txt.
> For full documentation content in one file, see https://docs.sarvam.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.sarvam.ai/_mcp/server.

# Generate Speech

POST https://api.sarvam.ai/voices/clone
Content-Type: multipart/form-data

Generates speech in a cloned voice from a reference audio clip or a saved cloned voice.

Accepts `multipart/form-data` - send `ref_audio` as a file upload and all other parameters as form fields.

**Two ways to clone:**

1. **Reference clip** - upload `ref_audio` (optionally with its transcript in `ref_text`).
2. **Saved voice** - pass a `voice_id` from your voice library; the stored reference audio and transcript are reused.

**Base URL:** `https://api.sarvam.ai`.
**Auth:** send your key in the `api-subscription-key` header (recommended); `Authorization: Bearer <key>` is also accepted.

The cloned voice is cross-lingual: the reference clip's language does not need to match `language_code`. The model preserves the speaker's timbre and identity while applying the phonetics and prosody of the target language.

**Billing:** charged per character of `text` against the `text_to_speech_voice_cloning` API. See the [pricing page](https://docs.sarvam.ai/api/getting-started/pricing).

Reference: https://docs.sarvam.ai/api-reference/voice-cloning/clone

## Authentication

- `api-subscription-key` header (required) — API Key authentication via header

## Request

### Body (multipart/form-data)

This endpoint expects a multipart form containing an optional file.

- `ref_audio` (file, optional) — Reference audio file for voice cloning. Supported formats: WAV, MP3, FLAC, OPUS, AAC, MULAW, ALAW, LINEAR16. WAV is recommended for best quality and fastest decoding. Limits: max file size 10 MB, max duration 30 seconds. Recommended duration is 10-15 seconds, single speaker, minimal background noise. Either `ref_audio` or `voice_id` is required. Sending both returns a 400 error.
- `voice_id` (string, optional) — Cloned voice ID (`svc-{uuid}`) from your voice library, created via the Content Studio Voice Library. When provided, the reference audio stored for that voice is used and `ref_audio` is not needed. Requires your API key to be bound to an organization. Sending both `ref_audio` and `voice_id` returns a 400 error.
- `text` (string, required) — Text to synthesize in the cloned voice. Native scripts and code-mixed text are supported. Maximum 1000 characters; longer text is rejected with a 400. Split longer input client-side and synthesize it in parts.
- `language_code` (enum, required) — BCP-47 language code for the synthesized output. The cloned voice can speak any supported language, regardless of the reference clip's language (cross-lingual cloning). **Available Options:** - `as-IN`: Assamese - `bn-IN`: Bengali - `en-IN`: English (Indian) - `gu-IN`: Gujarati - `hi-IN`: Hindi - `kn-IN`: Kannada - `ml-IN`: Malayalam - `mr-IN`: Marathi - `od-IN`: Odia - `pa-IN`: Punjabi - `ta-IN`: Tamil - `te-IN`: Telugu
- `pace` (double, optional) — Speech speed multiplier. `1.0` is natural speed; `0.5` to `2.0` is accepted. Speed is adjusted without changing pitch. Mutually exclusive with `max_audio_duration` - sending both returns a 400 error.
- `ref_text` (string, optional) — Transcript of the reference audio. Optional: when omitted with a `ref_audio` upload, the API transcribes the reference clip automatically. Providing the actual transcript improves fidelity, especially for cross-lingual cloning. Maximum length is 500 characters. When using `voice_id`, the stored reference transcript is used unless you override it here.
- `output_audio_codec` (enum, optional) — Audio codec for the output audio. Default is `wav`. - `wav`: Uncompressed. Best quality for downstream processing. - `mp3`: Smaller file size; suitable for web playback. - `flac`: Lossless compression. - `opus`: Low-bitrate codec ideal for streaming. When `speech_sample_rate` is explicitly set with `opus`, it must be one of 8000, 16000, 24000 or 48000 Hz; when omitted, opus output is returned at the native 24000 Hz. - `aac`: Common in mobile and broadcast. - `linear16`: Raw 16-bit PCM. - `mulaw` / `alaw`: 8-bit telephony codecs for IVR pipelines.
- `speech_sample_rate` (enum, optional) — Output sample rate in Hz. Supported values are 8000, 16000, 22050, 24000, 32000, 44100, 48000. If omitted, the API returns 24000 Hz. This is a service-side default: the output is resampled to it, so it does not change with the generating model. Set it to match your downstream pipeline: 8000 for telephony/IVR, 16000 for voice agents, 24000 for web playback, 44100/48000 for broadcast.
- `enable_qc` (boolean, optional) — Enable quality control: ASR transcription of the generated audio, character error rate (CER) scoring against the input text, and prompt-leak detection with bounded regeneration. Applies to single-chunk (short) generations; long text that is split into sentence chunks is generated without QC. Recommended for production use; disable only when you need the lowest latency or run your own downstream verification.
- `enable_cached_responses` (boolean, optional) — Enable response caching. Coming soon - accepted for forward compatibility, currently ignored.
- `enable_vad` (boolean, optional) — Enable VAD-based silence trimming of the generated audio. Default is `true`. Applies to single-chunk (short) generations; long text that is split into sentence chunks is returned untrimmed.
- `enable_text_normalization` (boolean, optional) — Enable pre-TTS text normalization: numbers, currencies and dates are converted to their spoken form before synthesis (e.g. `9840950950` becomes the spoken digit sequence). Defaults to the server-side setting. Supported for all 12 languages accepted by `language_code`; any other code passes through unchanged.
- `min_audio_duration` (double, optional) — Minimum output audio duration in seconds. If the generated audio is shorter, it is padded with silence.
- `max_audio_duration` (double, optional) — Maximum output audio duration in seconds. If the generated audio is longer, it is time-stretched to fit. Must be >= `min_audio_duration`. Silently floored to the reference clip's duration when the clip is longer. Mutually exclusive with `pace` - sending both returns a 400 error.
- `ref_audio_duration` (double, optional) — Override for the reference audio duration in seconds. Useful for dubbing/sync scenarios where the model should treat the reference as a specific length.

## Response

### 200

Successful Response

- `audio` (string, required) — Base64-encoded output audio in the requested codec.
- `request_id` (string, required) — Unique request identifier for debugging and support.
- `audio_duration` (double, optional, nullable) — Duration of the generated audio in seconds.

## Errors

### 400 Bad Request Error

Bad Request. Unsupported audio format, empty `text`, invalid duration range, or neither `ref_audio` nor `voice_id` provided.

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

### 402 Payment Required Error

Quota Exceeded

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

### 403 Forbidden Error

Forbidden. The `api-subscription-key` is missing, malformed, invalid.

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

### 422 Unprocessable Entity Error

Unprocessable Entity. The form fields failed validation; the body is invalid. Check enum values and required fields.

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

### 429 Too Many Requests Error

Rate Limit Exceeded. Retry with exponential backoff.

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

### 500 Internal Server Error

Internal Server Error. Model unavailable, generation failed, or QC could not produce a passing output. Retry once; if it persists, log the `request_id` and contact support.

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

### 502 Bad Gateway Error

Billing Service Unavailable. The billing service could not record usage for this request. Retry with exponential backoff; if it persists, contact support with the request_id.

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

### 503 Service Unavailable Error

Model Unavailable or Overloaded. The model call failed or the model is overloaded. Retry with exponential backoff.

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

### 504 Gateway Timeout Error

Gateway Timeout. The model call timed out. Retry with exponential backoff.

- `error` (object, required) — Error details
  - `request_id` (string, required, nullable)
  - `message` (string, required) — Message describing the error
  - `code` (enum, required) — Error code for the specific error that has occurred. Refer to the error code documentation for more details.
    - Allowed values: `invalid_request_error`, `internal_server_error`, `unprocessable_entity_error`, `insufficient_quota_error`, `invalid_api_key_error`, `authentication_error`, `not_found_error`, `rate_limit_exceeded_error`, `model_call_error`, `gateway_timeout_error`, `billing_service_unavailable_error`

## Examples

**Request**

```json
{
  "language_code": "hi-IN",
  "ref_audio": "<file: <file1>>",
  "ref_text": "Hello, this is a sample reference recording.",
  "text": "नमस्ते, मैं आपकी कैसे मदद कर सकता हूँ?"
}
```

**Response**

```json
{
  "audio": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAESsAACJWAAACABAAZGF0YQAAAAA=",
  "request_id": "20250101_0a1b2c3d-1234-5678-9abc-def012345678"
}
```

**SDK Code**

```typescript
import { SarvamAIClient } from "sarvamai";
import fs from "fs";

const client = new SarvamAIClient({
  apiSubscriptionKey: process.env.SARVAM_API_KEY,
});

const response = await client.voiceCloning.textToSpeech({
  text: "\u0928\u092e\u0938\u094d\u0924\u0947, \u092e\u0948\u0902 \u0906\u092a\u0915\u0940 \u0915\u0948\u0938\u0947 \u092e\u0926\u0926 \u0915\u0930 \u0938\u0915\u0924\u093e \u0939\u0942\u0901?",
  language_code: "hi-IN",
  refAudio: fs.createReadStream("reference.wav"),
  refText: "Hello, this is a sample reference recording.",
});

const audio = Buffer.from(response.audio, "base64");
fs.writeFileSync("output.wav", audio);

```

```typescript
import { SarvamAIClient } from "sarvamai";

async function main() {
    const client = new SarvamAIClient({
        apiSubscriptionKey: "YOUR_API_KEY_HERE",
    });
    await client.voiceCloning.textToSpeech({});
}
main();

```

```python
from sarvamai import SarvamAI

client = SarvamAI(
    api_subscription_key="YOUR_API_KEY_HERE",
)

client.voice_cloning.text_to_speech(
    ref_audio="example_ref_audio",
)

```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.sarvam.ai/voices/clone"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_cached_responses\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_qc\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_text_normalization\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_vad\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language_code\"\r\n\r\nhi-IN\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"max_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"min_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"output_audio_codec\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pace\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_audio\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_text\"\r\n\r\nHello, this is a sample reference recording.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"speech_sample_rate\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"text\"\r\n\r\nनमस्ते, मैं आपकी कैसे मदद कर सकता हूँ?\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voice_id\"\r\n\r\n\r\n-----011000010111000001101001--\r\n")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("api-subscription-key", "<apiSubscriptionKey>")
	req.Header.Add("Content-Type", "multipart/form-data; boundary=---011000010111000001101001")

	res, _ := http.DefaultClient.Do(req)

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

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.sarvam.ai/voices/clone")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["api-subscription-key"] = '<apiSubscriptionKey>'
request["Content-Type"] = 'multipart/form-data; boundary=---011000010111000001101001'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_cached_responses\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_qc\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_text_normalization\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_vad\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language_code\"\r\n\r\nhi-IN\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"max_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"min_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"output_audio_codec\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pace\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_audio\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_text\"\r\n\r\nHello, this is a sample reference recording.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"speech_sample_rate\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"text\"\r\n\r\nनमस्ते, मैं आपकी कैसे मदद कर सकता हूँ?\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voice_id\"\r\n\r\n\r\n-----011000010111000001101001--\r\n"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.sarvam.ai/voices/clone")
  .header("api-subscription-key", "<apiSubscriptionKey>")
  .header("Content-Type", "multipart/form-data; boundary=---011000010111000001101001")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_cached_responses\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_qc\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_text_normalization\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_vad\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language_code\"\r\n\r\nhi-IN\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"max_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"min_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"output_audio_codec\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pace\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_audio\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_text\"\r\n\r\nHello, this is a sample reference recording.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"speech_sample_rate\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"text\"\r\n\r\nनमस्ते, मैं आपकी कैसे मदद कर सकता हूँ?\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voice_id\"\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.sarvam.ai/voices/clone', [
  'multipart' => [
    [
        'name' => 'language_code',
        'contents' => 'hi-IN'
    ],
    [
        'name' => 'ref_audio',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'ref_text',
        'contents' => 'Hello, this is a sample reference recording.'
    ],
    [
        'name' => 'text',
        'contents' => 'नमस्ते, मैं आपकी कैसे मदद कर सकता हूँ?'
    ]
  ]
  'headers' => [
    'api-subscription-key' => '<apiSubscriptionKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.sarvam.ai/voices/clone");
var request = new RestRequest(Method.POST);
request.AddHeader("api-subscription-key", "<apiSubscriptionKey>");
request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_cached_responses\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_qc\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_text_normalization\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enable_vad\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"language_code\"\r\n\r\nhi-IN\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"max_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"min_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"output_audio_codec\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pace\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_audio\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_audio_duration\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"ref_text\"\r\n\r\nHello, this is a sample reference recording.\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"speech_sample_rate\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"text\"\r\n\r\nनमस्ते, मैं आपकी कैसे मदद कर सकता हूँ?\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"voice_id\"\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "api-subscription-key": "<apiSubscriptionKey>",
  "Content-Type": "multipart/form-data; boundary=---011000010111000001101001"
]
let parameters = [
  [
    "name": "enable_cached_responses",
    "value": 
  ],
  [
    "name": "enable_qc",
    "value": 
  ],
  [
    "name": "enable_text_normalization",
    "value": 
  ],
  [
    "name": "enable_vad",
    "value": 
  ],
  [
    "name": "language_code",
    "value": "hi-IN"
  ],
  [
    "name": "max_audio_duration",
    "value": 
  ],
  [
    "name": "min_audio_duration",
    "value": 
  ],
  [
    "name": "output_audio_codec",
    "value": 
  ],
  [
    "name": "pace",
    "value": 
  ],
  [
    "name": "ref_audio",
    "fileName": "<file1>"
  ],
  [
    "name": "ref_audio_duration",
    "value": 
  ],
  [
    "name": "ref_text",
    "value": "Hello, this is a sample reference recording."
  ],
  [
    "name": "speech_sample_rate",
    "value": 
  ],
  [
    "name": "text",
    "value": "नमस्ते, मैं आपकी कैसे मदद कर सकता हूँ?"
  ],
  [
    "name": "voice_id",
    "value": 
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.sarvam.ai/voices/clone")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```