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

# Fichiers

> Envoyez les fichiers d’entrée des lots et relisez-les par identifiant depuis n’importe quel SDK Phaseo.

Envoyez un fichier d’entrée de lot sous forme de formulaire multipart, conservez l’`id` renvoyé, puis relisez les métadonnées et les octets du fichier grâce à cet identifiant. Les exemples utilisent un `client` créé comme dans [Installation](https://phaseo.app/docs/fr/v1/sdk-reference/client/installation.md).

## Envoyer un fichier

TypeScript et Python envoient le fichier avec une méthode du SDK, qui appelle `POST /v1/batches/files`. Les autres SDK ne savent pas envoyer de multipart : ils envoient donc le formulaire à `POST /v1/files` avec le client HTTP standard.

```typescript TypeScript theme={null}
const uploaded = await client.uploadFile({
  purpose: "batch",
  file: new Blob(["{}"], { type: "application/json" }),
  filename: "batch.jsonl",
});
```

```python Python theme={null}
from pathlib import Path

uploaded = client.upload_file(
    purpose="batch",
    file=Path("batch.jsonl"),
    content_type="application/json",
)
```

```go Go theme={null}
// Le wrapper Go n’a pas de méthode d’envoi : envoyez le formulaire avec net/http et mime/multipart.
var body bytes.Buffer
form := multipart.NewWriter(&body)
_ = form.WriteField("purpose", "batch")
part, _ := form.CreateFormFile("file", "batch.jsonl")
data, _ := os.ReadFile("batch.jsonl")
_, _ = part.Write(data)
_ = form.Close()

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

resp, err := http.DefaultClient.Do(req) // conservez l’id renvoyé
```

```csharp C# theme={null}
// UploadFile() envoie du JSON : envoyez le formulaire avec HttpClient.
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new("Bearer", Environment.GetEnvironmentVariable("PHASEO_API_KEY"));

using var form = new MultipartFormDataContent
{
    { new StringContent("batch"), "purpose" },
    { new ByteArrayContent(await File.ReadAllBytesAsync("batch.jsonl")), "file", "batch.jsonl" },
};

var uploaded = await http.PostAsync("https://api.phaseo.app/v1/files", form);
Console.WriteLine(await uploaded.Content.ReadAsStringAsync()); // conservez l’id renvoyé
```

```php PHP theme={null}
// uploadFile() envoie du JSON : envoyez le formulaire avec Guzzle.
$http = new GuzzleHttp\Client();

$uploaded = $http->post('https://api.phaseo.app/v1/files', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('PHASEO_API_KEY')],
    'multipart' => [
        ['name' => 'purpose', 'contents' => 'batch'],
        ['name' => 'file', 'contents' => fopen('batch.jsonl', 'r'), 'filename' => 'batch.jsonl'],
    ],
]);

$fileId = json_decode((string) $uploaded->getBody(), true)['id'];
```

```ruby Ruby theme={null}
# upload_file envoie du JSON : envoyez le formulaire avec Net::HTTP.
require 'net/http'
require 'json'

uri = URI('https://api.phaseo.app/v1/files')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{ENV.fetch('PHASEO_API_KEY')}"
request.set_form([['purpose', 'batch'], ['file', File.open('batch.jsonl')]], 'multipart/form-data')

response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
file_id = JSON.parse(response.body)['id']
```

```java Java theme={null}
// Les assistants JSON du SDK n’encodent pas le multipart : envoyez le formulaire avec 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=\"purpose\"\r\n\r\nbatch\r\n"),
    BodyPublishers.ofString("--" + boundary + "\r\nContent-Disposition: form-data; name=\"file\"; filename=\"batch.jsonl\"\r\nContent-Type: application/jsonl\r\n\r\n"),
    BodyPublishers.ofFile(Path.of("batch.jsonl")),
    BodyPublishers.ofString("\r\n--" + boundary + "--\r\n")
);
var request = HttpRequest.newBuilder(URI.create(baseUrl + "/files"))
    .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()); // conservez l’id renvoyé
```

### Options d’envoi

Elles s’appliquent aux méthodes d’envoi TypeScript et Python. Dans les requêtes multipart brutes, envoyez `purpose` et `file` comme champs de formulaire.

| TypeScript | Python | Remarques |
| - | - | - |
| `file` | `file` | Obligatoire. TypeScript : un `Blob`, un `File`, un `BufferSource` ou une chaîne. Python : des `bytes`, un `Path`, un objet fichier ou un tuple de fichier HTTPX ; une simple chaîne lève `TypeError`. |
| `purpose` | `purpose` | Par exemple `batch`. |
| `filename`, `contentType` | `filename`, `content_type` | Nom et type de média du fichier envoyé. En Python, un `Path` utilise son propre nom de fichier. |
| `model`, `provider` | aucun | TypeScript uniquement. Choisissent le fournisseur de lots qui stocke le fichier. Sans l’un ni l’autre, le fichier va chez OpenAI. En Python, les envois vont toujours au fournisseur de lots OpenAI par défaut. |

## Relire un fichier

```typescript TypeScript theme={null}
const file = await client.getFile(uploaded.id);
const content = await client.getFileContent(uploaded.id); // Uint8Array
```

```python Python theme={null}
file_obj = client.get_file(uploaded["id"])
file_bytes = client.get_file_content(uploaded["id"])  # bytes
```

```go Go theme={null}
file, err := client.RetrieveFile(context.Background(), "file_123")
if err != nil {
  panic(err)
}

content, err := client.RetrieveFileContent(context.Background(), "file_123") // []byte
if err != nil {
  panic(err)
}

fmt.Println(file)
fmt.Println(string(content))
```

```csharp C# theme={null}
var file = await client.RetrieveFile("file_123");
byte[] content = await client.RetrieveFileContent("file_123");
```

```php PHP theme={null}
$file = $client->retrieveFile('file_123');
$content = $client->retrieveFileContent('file_123');
```

```ruby Ruby theme={null}
file = client.retrieve_file('file_123')
content = client.retrieve_file_content('file_123')
```

```java Java theme={null}
import java.nio.charset.StandardCharsets;

var file = client.retrieveFile("file_123");
byte[] content = client.retrieveFileContent("file_123");
System.out.println(file);
System.out.println(new String(content, StandardCharsets.UTF_8));
```

Remplacez `file_123` par l’identifiant renvoyé lors de l’envoi.

| Langage | Métadonnées | Contenu | Méthode d’envoi | Liste |
| - | - | - | - | - |
| TypeScript | `getFile(id)` | `getFileContent(id)`, un `Uint8Array` | `uploadFile(...)`, en multipart | `listFiles()` |
| Python | `get_file(id)` | `get_file_content(id)`, des `bytes` | `upload_file(...)`, en multipart | `list_files()` |
| Go | `RetrieveFile(ctx, id)` | `RetrieveFileContent(ctx, id)`, un `[]byte` | Aucune | `ListFiles(ctx, query)` |
| C# | `RetrieveFile(id)` | `RetrieveFileContent(id)`, un `byte[]` | `UploadFile(request)` envoie du JSON et ne peut donc pas envoyer de fichier | `ListFiles(query)` |
| PHP | `retrieveFile($id)` | `retrieveFileContent($id)` | `uploadFile($payload)` envoie du JSON et ne peut donc pas envoyer de fichier | `listFiles($params)` |
| Ruby | `retrieve_file(id)` | `retrieve_file_content(id)` | `upload_file(payload)` envoie du JSON et ne peut donc pas envoyer de fichier | `list_files(...)` |
| Java | `retrieveFile(id)` | `retrieveFileContent(id)`, un `byte[]` | `uploadFile(request)` envoie du JSON et ne peut donc pas envoyer de fichier | `listFiles(query)` |

En Python, vous pouvez aussi passer par `client.files` : `create(params)` envoie le fichier comme `upload_file`, `list()` liste, `retrieve(id)` lit les métadonnées et `content(id)` lit les octets. Rust n’a pas de méthode pour les fichiers.

> [!NOTE]
>
> Les endpoints de fichiers sont en bêta et nécessitent un fournisseur de lots activé.

## Conservez l’identifiant du fichier : vous ne pouvez pas lister les fichiers

Enregistrez l’`id` de chaque fichier envoyé. Les méthodes de liste appellent `GET /v1/files`, qui renvoie `400` avec le code `not_supported` et le motif `file_list_not_supported_with_shared_gateway_key`. Le contrat complet se trouve dans la [référence de l’API Files](https://phaseo.app/docs/fr/v1/api-reference/endpoint/files.md).

## Réponse

`FileObject`, renvoyé par l’envoi et par les méthodes de métadonnées :

```json theme={null}
{
  "id": "file-123",
  "object": "file",
  "filename": "data.json",
  "purpose": "batch",
  "status": "processed",
  "created_at": 1677610602,
  "bytes": 123
}
```


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