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

> ## Agent Instructions
> Phaseo Gateway base URL: https://api.phaseo.app/v1. Send `Authorization: Bearer $PHASEO_API_KEY` with every request.
> Model IDs look like `provider/model`, for example `openai/gpt-6-astra`. Do not guess IDs: list them with `GET /v1/models` or check https://phaseo.app/models. `phaseo/free` routes to an available free model and needs no wallet balance.
> For new text integrations prefer `POST /v1/responses`. `POST /v1/chat/completions` (OpenAI format) and `POST /v1/messages` (Anthropic format) suit existing code.
> The full API contract is https://phaseo.app/docs/openapi/v1/openapi.yaml. Official SDKs: `@phaseo/sdk` (TypeScript) and `phaseo` (Python), plus Go, C#, PHP, Ruby and Rust.
> Search these docs over MCP at https://phaseo.app/docs/mcp, and install Phaseo skills with `npx skills add https://phaseo.app/docs`. If a page is wrong or out of date, report it with the MCP `submit_feedback` tool.
> Manage Phaseo accounts with the `phaseo` CLI (`npm install -g @phaseo/cli`, then `phaseo login` or `phaseo login --device-code`), the `/v1` Management API or the MCP server at `https://mcp.phaseo.app/mcp?access=manage`. Do not send users to the dashboard for account tasks. A person is still needed for sign-up, approving a sign-in, paying the first top-up on the checkout link that `phaseo credits add` returns when no card is saved, confirming each saved-card top-up from the emailed link, and account security (password, MFA, passkeys). Create API keys with `phaseo keys create --name <name> --json`; never guess one. Credit top-ups need `phaseo login --scopes billing:write` first. Task map: https://phaseo.app/docs/v1/developers/manage-from-an-agent.md.

# STT (voz a texto)

> Transcribe audio con POST /v1/audio/transcriptions desde cualquier SDK de Phaseo.

Sube el audio a `POST /v1/audio/transcriptions` como un formulario multipart con un campo `file`. Un cuerpo JSON con una cadena en base64 no supera la validación. Solo el SDK de TypeScript puede enviar ese formulario; en los demás lenguajes, envíalo con el cliente HTTP estándar, como se muestra abajo, o envía una URL en su lugar (consulta [Transcribe audio desde una URL](#transcribe-audio-from-a-url)).

## Sube un archivo de audio

```typescript TypeScript theme={null}
import { readFile } from "node:fs/promises";

const form = new FormData();
form.append("model", "openai/gpt-4o-transcribe");
form.append("language", "en");
form.append("file", new Blob([await readFile("call.mp3")], { type: "audio/mpeg" }), "call.mp3");

const transcript = await client.generateTranscription(form as unknown as Record<string, unknown>);
console.log(transcript.text);
```

```python Python theme={null}
# generate_transcription() todavía no puede enviar multipart, así que envía el formulario con HTTPX.
import os
import httpx

with open("call.mp3", "rb") as audio:
    response = httpx.post(
        "https://api.phaseo.app/v1/audio/transcriptions",
        headers={"Authorization": f"Bearer {os.environ['PHASEO_API_KEY']}"},
        data={"model": "openai/gpt-4o-transcribe", "language": "en"},
        files={"file": ("call.mp3", audio, "audio/mpeg")},
        timeout=120,
    )
response.raise_for_status()
print(response.json()["text"])
```

```go Go theme={null}
// CreateTranscription() envía JSON, así que envía el formulario con net/http y mime/multipart.
var body bytes.Buffer
form := multipart.NewWriter(&body)
_ = form.WriteField("model", "openai/gpt-4o-transcribe")
_ = form.WriteField("language", "en")
part, _ := form.CreateFormFile("file", "call.mp3")
audio, _ := os.ReadFile("call.mp3")
_, _ = part.Write(audio)
_ = form.Close()

req, _ := http.NewRequest("POST", "https://api.phaseo.app/v1/audio/transcriptions", &body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("PHASEO_API_KEY"))
req.Header.Set("Content-Type", form.FormDataContentType())

resp, err := http.DefaultClient.Do(req)
```

```csharp C# theme={null}
// CreateTranscription() envía JSON, así que envía el formulario con HttpClient.
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new("Bearer", Environment.GetEnvironmentVariable("PHASEO_API_KEY"));

using var form = new MultipartFormDataContent
{
    { new StringContent("openai/gpt-4o-transcribe"), "model" },
    { new StringContent("en"), "language" },
    { new ByteArrayContent(await File.ReadAllBytesAsync("call.mp3")), "file", "call.mp3" },
};

var response = await http.PostAsync("https://api.phaseo.app/v1/audio/transcriptions", form);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```

```php PHP theme={null}
<?php
// generateTranscription() envía JSON, así que envía el formulario con Guzzle, que Composer instaló con el SDK.
require 'vendor/autoload.php';

$http = new GuzzleHttp\Client();

$response = $http->post('https://api.phaseo.app/v1/audio/transcriptions', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('PHASEO_API_KEY')],
    'multipart' => [
        ['name' => 'model', 'contents' => 'openai/gpt-4o-transcribe'],
        ['name' => 'language', 'contents' => 'en'],
        ['name' => 'file', 'contents' => fopen('call.mp3', 'r'), 'filename' => 'call.mp3'],
    ],
]);

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

```ruby Ruby theme={null}
# generate_transcription envía JSON, así que envía el formulario con Net::HTTP.
require 'net/http'

uri = URI('https://api.phaseo.app/v1/audio/transcriptions')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{ENV.fetch('PHASEO_API_KEY')}"
request.set_form(
  [['model', 'openai/gpt-4o-transcribe'], ['language', 'en'], ['file', File.open('call.mp3')]],
  'multipart/form-data'
)

response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
puts response.body
```

```java Java theme={null}
// Los helpers JSON del SDK no codifican multipart, así que envía el formulario con java.net.http.
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.file.Path;
import java.time.Duration;
import java.util.UUID;

String baseUrl = System.getenv().getOrDefault("PHASEO_BASE_URL", "https://api.phaseo.app/v1")
    .replaceAll("/+$", "");
String apiKey = System.getenv("PHASEO_API_KEY");
String boundary = "phaseo-" + UUID.randomUUID();
var body = BodyPublishers.concat(
    BodyPublishers.ofString("--" + boundary + "\r\nContent-Disposition: form-data; name=\"model\"\r\n\r\nopenai/gpt-4o-transcribe\r\n"),
    BodyPublishers.ofString("--" + boundary + "\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\nen\r\n"),
    BodyPublishers.ofString("--" + boundary + "\r\nContent-Disposition: form-data; name=\"file\"; filename=\"call.mp3\"\r\nContent-Type: audio/mpeg\r\n\r\n"),
    BodyPublishers.ofFile(Path.of("call.mp3")),
    BodyPublishers.ofString("\r\n--" + boundary + "--\r\n")
);
var request = HttpRequest.newBuilder(URI.create(baseUrl + "/audio/transcriptions"))
    .header("Authorization", "Bearer " + apiKey)
    .header("Content-Type", "multipart/form-data; boundary=" + boundary)
    .timeout(Duration.ofSeconds(60))
    .POST(body)
    .build();
var response = HttpClient.newHttpClient().send(request, BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
    throw new IOException("HTTP " + response.statusCode() + ": " + response.body());
}
System.out.println(response.body());
```

| Lenguaje | Método del SDK | ¿Puede subir un archivo? |
| - | - | - |
| TypeScript | `client.generateTranscription(form)` | Sí. Pasa un cuerpo `FormData` y el SDK lo envía como multipart sin cambios. La conversión de tipo es necesaria porque el tipo del método describe un cuerpo JSON. |
| Python | `client.generate_transcription(request)` | No. Siempre envía JSON, así que envía el formulario con HTTPX, como arriba. |
| Go | `client.CreateTranscription(ctx, req)` | No. Envía JSON; usa `net/http` y `mime/multipart`. |
| C# | `client.CreateTranscription(request)` | No. Envía JSON; usa `HttpClient` y `MultipartFormDataContent`. |
| PHP | `$client->generateTranscription($request)`, alias `createTranscription()` | No. Envía JSON; usa la opción `multipart` de Guzzle. |
| Ruby | `client.generate_transcription(...)`, alias `create_transcription` | No. Envía JSON; usa `Net::HTTP` y `set_form`. |
| Java | Ninguno | No. Usa `java.net.http.HttpClient` con un cuerpo multipart. |
| Rust | Ninguno | No. `client.post()` solo envía JSON, así que solo sirve para [fuentes de URL](#transcribe-audio-from-a-url). |

## Transcribe audio desde una URL

Los modelos de Mistral, ElevenLabs y Morpheus pueden leer el audio desde una URL en lugar de una subida. Como esta solicitud es JSON, los métodos del SDK que no pueden subir un archivo sí la gestionan:

```python Python theme={null}
result = client.generate_transcription({
    "model": "mistral/voxtral-mini-transcribe-2",
    "file_url": "https://example.com/call.mp3",
    "language": "en",
})

print(result["text"])
```

```go Go theme={null}
resp, err := client.CreateTranscription(context.Background(), map[string]interface{}{
  "model":    "mistral/voxtral-mini-transcribe-2",
  "file_url": "https://example.com/call.mp3",
  "language": "en",
})
if err != nil {
  panic(err)
}
fmt.Println(resp["text"])
```

```csharp C# theme={null}
var response = await client.CreateTranscription(new Dictionary<string, object>
{
    ["model"] = "mistral/voxtral-mini-transcribe-2",
    ["file_url"] = "https://example.com/call.mp3",
    ["language"] = "en",
});
```

```php PHP theme={null}
$response = $client->generateTranscription([
    'model' => 'mistral/voxtral-mini-transcribe-2',
    'file_url' => 'https://example.com/call.mp3',
    'language' => 'en',
]);

echo $response['text'];
```

```ruby Ruby theme={null}
response = client.generate_transcription(
  model: 'mistral/voxtral-mini-transcribe-2',
  file_url: 'https://example.com/call.mp3',
  language: 'en'
)
```

```rust Rust theme={null}
let response = client.post("/audio/transcriptions", &json!({
    "model": "mistral/voxtral-mini-transcribe-2",
    "file_url": "https://example.com/call.mp3",
    "language": "en"
}))?;

println!("{}", response.body["text"]);
```

## Parámetros

Los nombres de los campos son los del formulario (o los campos JSON para una fuente de URL) en todos los lenguajes.

| Campo | Notas |
| - | - |
| `model` | Obligatorio. Un ID de modelo de transcripción. |
| `file` | El audio subido: `aac`, `flac`, `mp3`, `mp4`, `mpeg`, `mpga`, `m4a`, `ogg`, `opus`, `wav` o `webm`. Obligatorio salvo con las opciones de URL de abajo. Hasta 25 MB en la mayoría de los modelos. |
| `file_url`, `file_id`, `s3_presigned_url` | Los modelos de Mistral, ElevenLabs y Morpheus aceptan exactamente una fuente de audio, así que pueden usar una URL en lugar de `file`. |
| `language` | Indicación del idioma, como `en`. |
| `prompt` | Contexto para mejorar la precisión. |
| `temperature` | De `0` a `1` (de `0` a `2` en ElevenLabs). |
| `response_format` | `json`, `text`, `srt`, `verbose_json`, `vtt` o `diarized_json`. |
| `timestamp_granularities` | `word` o `segment`, o ambos. |
| `stream` | Transmite la transcripción a medida que se genera, si el modelo lo admite. |

El esquema completo está en la [referencia de la API de transcripciones](https://phaseo.app/docs/es/v1/api-reference/endpoint/audio-transcriptions.md).

## Respuesta

`AudioTranscriptionResponse`, devuelto como el tipo map de cada SDK (`map[string]interface{}` en Go, `Dictionary<string, object>?` en C#, un array en PHP, un Hash en Ruby):

```json theme={null}
{
  "text": "Hello world"
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.