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

# Migrer vers la v6

> Ce qui a changé entre @squarecloud/api v5 et v6 : des données brutes au lieu de classes, les identifiants en premier argument, une seule classe d'erreur, des timeouts et des nouvelles tentatives. Un tableau méthode par méthode.

La v6 est une réécriture : un client plat unique, des données brutes au lieu de classes, les identifiants en premier argument et une seule classe d'erreur. La plupart des changements sont mécaniques.

## En un coup d'œil

| v5                                                                                                    | v6                                                                                                                                                                                         |
| ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Des classes avec des méthodes (`app.start()`)                                                         | Des données brutes ; les méthodes sont sur le client (`api.apps.start(appId)`)                                                                                                             |
| `Collection`                                                                                          | `Array`                                                                                                                                                                                    |
| Champs de classe en camelCase avec des `Date` (`createdAt`, `modifiedAt`, `uptime`)                   | Les champs et valeurs propres à l'API (`created_at` et `modified` en chaînes ISO, `uptime` en ms)                                                                                          |
| `Buffer`                                                                                              | `Uint8Array` (un `Buffer` est toujours accepté en entrée)                                                                                                                                  |
| Les mutations renvoient `Promise<boolean>` (toujours `true`)                                          | `Promise<void>`, ou les données renvoyées par l'API (`envs.*` → `EnvVars`, `deploys.setWebhook` → URL, `deploys.linkGithubApp` → `LinkedRepository`, `resetCredentials` → le mot de passe) |
| `SquareCloudAPIError extends TypeError` avec seulement `code`                                         | `extends Error` avec `status`, `code`, `message` (celui du serveur), `method`, `path`, `cause`                                                                                             |
| Événements (`userUpdate`, `statusUpdate`, `logsUpdate`, `snapshotsUpdate`) et `api.cache`/`app.cache` | Supprimés : gérez votre propre état                                                                                                                                                        |
| `api.api.request()` (l'`APIService` brut)                                                             | Supprimé : chaque opération a une méthode                                                                                                                                                  |
| Pas de timeout, pas de nouvelles tentatives                                                           | Timeout de 30 s par tentative, nouvelles tentatives uniquement pour les échecs sans risque (voir [Changements de comportement](#changements-de-comportement))                              |
| Node.js >= 20                                                                                         | Node.js >= 22, Deno, Bun, edge                                                                                                                                                             |
| `@squarecloud/api-types`                                                                              | Les types sont livrés avec le SDK (`import type { App } from "@squarecloud/api"`)                                                                                                          |

## Construction et options

| v5                        | v6                                                                                   | Remarques                                                                                                                                                           |
| ------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `new SquareCloudAPI(key)` | `new SquareCloudAPI(key, { baseUrl?, timeoutMs?, maxRetries?, userAgent?, fetch? })` | Une clé vide ou composée uniquement d'espaces lève une `TypeError`.                                                                                                 |
| `SquareCloudAPI.apiInfo`  | `BASE_URL` et `{ baseUrl }`                                                          | `BASE_URL` = `https://api.squarecloud.app/v2`.                                                                                                                      |
| (aucun)                   | `timeoutMs` (30000)                                                                  | Par tentative ; les appels maintenus ouverts et `ai.chat` attendent au moins 120 s. `<= 0`, `Infinity` ou `>= 2^31` désactive tous les timeouts, planchers compris. |
| (aucun)                   | `maxRetries` (2)                                                                     | Uniquement les erreurs réseau sur GET et les codes 503 listés ; jamais 429.                                                                                         |
| (aucun)                   | `userAgent`                                                                          | Remplace l'en-tête entier (par défaut `squarecloud-sdk-js/<version>`).                                                                                              |
| (aucun)                   | `fetch`                                                                              | `fetch` personnalisé (proxys, traçage, tests).                                                                                                                      |

## Méthode par méthode

| v5                                                                           | v6                                                                                                        | Remarques                                                                                                                                                                             |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `api.user.get()` → `User`                                                    | `api.account.me()`                                                                                        | Renvoie `{ user, applications, databases }`.                                                                                                                                          |
| `user.plan.expiresIn`                                                        | `new Date(user.plan.duration)`                                                                            | Un horodatage ; `null` n'expire jamais.                                                                                                                                               |
| `api.user.snapshots(scope)`                                                  | `api.account.snapshots({ scope })`                                                                        |                                                                                                                                                                                       |
| `api.service.status()`                                                       | `api.service.status()`                                                                                    | Nouvelle forme : `status`, `message`, `services`, `dependencies`...                                                                                                                   |
| `api.applications.get()`                                                     | `(await api.account.me()).applications`                                                                   |                                                                                                                                                                                       |
| `api.applications.get(id)` / `fetch(id)` / `app.fetch()`                     | `api.apps.get(id)`                                                                                        | Trouve aussi les applications partagées via un workspace.                                                                                                                             |
| `app.isWebsite()`                                                            | `Boolean((await api.apps.get(id)).domain)`                                                                |                                                                                                                                                                                       |
| `api.applications.create(file)`                                              | `api.apps.create(file, { signal })`                                                                       | Un chemin, un `Blob`/`File` ou un `Uint8Array` ; pas de timeout.                                                                                                                      |
| `api.applications.statusAll()`                                               | `api.apps.statusAll({ workspaceId? })`                                                                    | Objets bruts `{ id, running, cpu?, ram? }` (la v5 imbriquait `cpu`/`ram` sous `usage`).                                                                                               |
| `statusAll()[i].fetch()` (`SimpleApplicationStatus`, `SimpleDatabaseStatus`) | `api.apps.status(id)` / `api.databases.status(id)`                                                        |                                                                                                                                                                                       |
| `api.applications.domains()` / `loadBalancers()`                             | `api.apps.domains()` / `api.apps.loadBalancers()`                                                         |                                                                                                                                                                                       |
| `app.getStatus()`                                                            | `api.apps.status(id, { raw? })`                                                                           | `cpu`, `ram`, `storage` et `network` sont au premier niveau (la v5 les imbriquait sous `usage`) ; `uptime` est l'horodatage de démarrage en ms (`null` à l'arrêt), et non une `Date`. |
| `app.getLogs()`                                                              | `api.apps.logs(id)`                                                                                       |                                                                                                                                                                                       |
| `app.getMetrics()`                                                           | `api.apps.metrics(id)`                                                                                    | Le point le plus récent en premier.                                                                                                                                                   |
| `app.realtime()` → `Response` brute                                          | `api.apps.realtime(id, { signal })`                                                                       | Un itérable asynchrone d'événements analysés.                                                                                                                                         |
| `app.start()` / `stop()` / `restart()` / `delete()`                          | `api.apps.start(id)` / `stop(id)` / `restart(id)` / `delete(id)`                                          |                                                                                                                                                                                       |
| `app.commit(file, fileName)`                                                 | `api.apps.commit(id, file, { path?, filename?, signal? })`                                                |                                                                                                                                                                                       |
| `app.files.list(path)`                                                       | `api.apps.files.list(id, path?)`                                                                          | Un répertoire manquant lève 404 `FILE_NOT_FOUND` (auparavant, une liste vide).                                                                                                        |
| `app.files.read(path)` → `Buffer \| undefined`                               | `api.apps.files.read(id, path)` → `Uint8Array`                                                            | Demandé en base64 puis décodé (la v5 lisait un tableau d'octets). Des octets vides, jamais `undefined`, quand l'API n'envoie aucun contenu.                                           |
| `app.files.create(file, fileName, dir)`                                      | ``api.apps.files.write(id, `${dir}/${fileName}`, content)``                                               | Une chaîne est le **contenu** (envoyé en texte brut) ; la v5 la lisait comme un chemin local. Les octets sont envoyés en base64. Un contenu vide crée un fichier vide.                |
| `app.files.edit(file, path)`                                                 | `api.apps.files.write(id, path, content)`                                                                 | Même format de transmission que `write` : du texte pour les chaînes, du base64 pour les octets.                                                                                       |
| `app.files.move(path, newPath)` / `delete(path)`                             | `api.apps.files.move(id, path, to)` / `delete(id, path)`                                                  |                                                                                                                                                                                       |
| `app.envs.list()`                                                            | `api.apps.envs.get(id)`                                                                                   |                                                                                                                                                                                       |
| `app.envs.set(envs)` / `replace(envs)` / `delete(keys)`                      | `api.apps.envs.set(id, envs)` / `replace(id, envs)` / `delete(id, keys)`                                  | Chacune renvoie les variables résultantes.                                                                                                                                            |
| `app.snapshots.list()`                                                       | `api.apps.snapshots.list(id)`                                                                             | Les éléments gagnent `name`, `runtime`, `origin`, `version_id` et une `url` de téléchargement signée, le tout tel que l'API les envoie.                                               |
| `app.snapshots.create()`                                                     | `api.apps.snapshots.create(id)`                                                                           | `{ pending: true }` sur un 202 (la v5 levait une erreur), sinon `{ pending: false, url, key }`.                                                                                       |
| `app.snapshots.download()` → `Buffer`                                        | `const s = await api.apps.snapshots.create(id)`, puis `if (!s.pending) await api.downloadSnapshot(s.url)` | Un `ReadableStream`, rien en mémoire tampon. Un snapshot en attente (202) n'a pas encore d'URL : la v5 levait une erreur.                                                             |
| `snapshot.url` / `snapshot.download()`                                       | `snapshot.url` / `api.downloadSnapshot(snapshot.url)`                                                     | L'URL signée propre à l'API (la v5 en construisait une erronée à partir de l'identifiant de l'appelant).                                                                              |
| `app.snapshots.restore({ snapshotId, versionId })`                           | `api.apps.snapshots.restore(id, name, versionId)`                                                         | Passez le `name` et le `version_id` d'un snapshot listé. Voir [Snapshots](/fr/sdks/js/snapshots#restaurer-un-snapshot) pour les erreurs.                                              |
| `app.deploys.integrateGithubWebhook(token)`                                  | `api.apps.deploys.setWebhook(id, token)`                                                                  | Renvoie l'URL du webhook (`""` lorsqu'il est supprimé avec `"@"`).                                                                                                                    |
| `app.deploys.linkGithubApp({ repositoryName, repositoryBranch })`            | `api.apps.deploys.linkGithubApp(id, repository, branch)`                                                  | Arguments positionnels. Renvoie `{ id, full_name, branch }`. Les clés API sont désormais acceptées (scope `apps:deploy`) ; la v5 exigeait un JWT de session.                          |
| `app.deploys.unlinkGithubApp()` → `boolean`                                  | `api.apps.deploys.unlinkGithubApp(id)`                                                                    | Se résout en `void` (auparavant `boolean`). `400 GIT_NOT_CONFIGURED` quand rien n'est lié.                                                                                            |
| `app.deploys.list()` → `Deployment[][]`                                      | `api.apps.deploys.list(id)` → `DeployEvent[][]`                                                           | Un deploy échoué se termine par `state: "error"` avec `code` (et `message` lorsqu'il y a des détails) ; `source` vaut toujours `"git"`.                                               |
| `app.deploys.current()`                                                      | `api.apps.deploys.current(id)` → `DeployCurrent`                                                          | `{}` quand rien n'est configuré.                                                                                                                                                      |
| `app.deploys.webhookURL()`                                                   | `(await api.apps.deploys.current(id)).webhook`                                                            |                                                                                                                                                                                       |
| `app.network` (uniquement sur `WebsiteApplication`)                          | `api.apps.network`                                                                                        | N'importe quel identifiant d'application ; l'API rejette les applications non web.                                                                                                    |
| `network.setCustomDomain(domain)`                                            | `api.apps.network.setDomain(id, domain)`                                                                  |                                                                                                                                                                                       |
| `network.analytics({ start, end, contentType, ... })`                        | `api.apps.network.analytics(id, start, end, { content_type, ... })`                                       | `null` pour une fenêtre vide.                                                                                                                                                         |
| `network.errors({ start, end, include4xx })`                                 | `api.apps.network.errors(id, start, end, { include_4xx })`                                                | `null` pour une fenêtre vide.                                                                                                                                                         |
| `network.logs({ start, end })` / `performance({ start, end })`               | `api.apps.network.logs(id, start, end)` / `performance(id, start, end)`                                   |                                                                                                                                                                                       |
| `network.dns()` / `purgeCache()`                                             | `api.apps.network.dns(id)` / `purgeCache(id)`                                                             |                                                                                                                                                                                       |
| `api.databases.fetch(id)` / `db.fetch()`                                     | `api.databases.get(id)`                                                                                   |                                                                                                                                                                                       |
| `api.databases.create(options)` / `statusAll()`                              | inchangé                                                                                                  | `statusAll()` renvoie des objets bruts `{ id, running, cpu?, ram? }`.                                                                                                                 |
| `db.getStatus()` / `getMetrics()`                                            | `api.databases.status(id, { raw? })` / `metrics(id)`                                                      | `ram` est la RAM utilisée, par ex. `"120.4MB"` (un nombre avec `raw`). Les métriques arrivent du plus récent au plus ancien.                                                          |
| `db.start()` / `stop()` / `update(changes)` / `delete()`                     | `api.databases.start(id)` / `stop(id)` / `update(id, changes)` / `delete(id)`                             |                                                                                                                                                                                       |
| `db.credentials.certificate()`                                               | `api.databases.certificate(id)`                                                                           |                                                                                                                                                                                       |
| `db.credentials.reset(type)`                                                 | `api.databases.resetCredentials(id, type)`                                                                | Le nouveau mot de passe (`""` pour `"certificate"`).                                                                                                                                  |
| `db.snapshots.list()` / `create()` / `download()`                            | `api.databases.snapshots.list(id)` / `create(id)` / `api.downloadSnapshot(url)`                           | `download()` comme pour les applications : `create(id)`, puis `downloadSnapshot(s.url)` lorsqu'il n'est pas en attente.                                                               |
| `db.snapshots.restore(snapshotId, versionId)`                                | `api.databases.snapshots.restore(id, name, versionId)`                                                    | Passez le `name` et le `version_id` d'un snapshot listé.                                                                                                                              |
| `api.workspaces.list()` / `fetch(id)` / `workspace.fetch()`                  | `api.workspaces.list()` / `get(id)`                                                                       |                                                                                                                                                                                       |
| `api.workspaces.create({ name })`                                            | `api.workspaces.create(name)`                                                                             | Renvoie `WorkspaceCreated` (`{ id, name }`).                                                                                                                                          |
| `api.workspaces.delete(id)` / `workspace.delete()`                           | `api.workspaces.delete(id)`                                                                               |                                                                                                                                                                                       |
| `api.workspaces.leave(id)` / `workspace.leave()`                             | `api.workspaces.leave(id)`                                                                                |                                                                                                                                                                                       |
| `api.workspaces.generateInviteCode()`                                        | `api.workspaces.members.inviteCode()`                                                                     |                                                                                                                                                                                       |
| `workspace.members.add(code, group)`                                         | `api.workspaces.members.add(workspaceId, code, group)`                                                    |                                                                                                                                                                                       |
| `workspace.members.update(memberId, group)` / `remove(memberId)`             | `api.workspaces.members.update(workspaceId, memberId, group)` / `remove(workspaceId, memberId)`           |                                                                                                                                                                                       |
| `workspace.applications.add(appId)` / `remove(appId)`                        | `api.workspaces.apps.add(workspaceId, appId)` / `remove(workspaceId, appId)`                              |                                                                                                                                                                                       |
| (aucun)                                                                      | `api.ai.chat(request)`, `api.downloadSnapshot(url)`, `BASE_URL`                                           | Nouveau.                                                                                                                                                                              |

## Types

Les types sont livrés avec le SDK et reprennent les noms de champs de l'API. Les principaux renommages depuis `@squarecloud/api-types` et les classes de la v5 :

| v5                                                                                                                                                                            | v6                                                                                             |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `Application`, `WebsiteApplication`, `BaseApplication`                                                                                                                        | `App` (`api.apps.get()`), `AppSummary` (`account.me()`), `AppCreated`                          |
| `ApplicationStatus`, `SimpleApplicationStatus`, `SimpleDatabaseStatus`                                                                                                        | `RuntimeStats` (`RuntimeStats<true>` avec `{ raw: true }`), `StatusListItem`                   |
| `User`                                                                                                                                                                        | `Account` (`{ user, applications, databases }`), `User`, `Plan`                                |
| `Snapshot`, `DatabaseSnapshot`                                                                                                                                                | `Snapshot`, `SnapshotCreated`                                                                  |
| `Deployment`, `DeploymentState`                                                                                                                                               | `DeployEvent`, `DeployCurrent` (avec `DeployRepository`), `LinkedRepository`                   |
| Objets de requête réseau                                                                                                                                                      | `AnalyticsFilters` (les filtres optionnels ; `start` et `end` sont des arguments)              |
| `Workspace`                                                                                                                                                                   | `Workspace`, `WorkspaceCreated`, `WorkspaceGroup`                                              |
| `APIErrorCode` (objet à l'exécution)                                                                                                                                          | `ErrorCode` (uniquement un type, sans coût à l'exécution ; tous les codes du contrat de l'API) |
| `APIEndpoint`, `APIEndpoints`, `APIMethod`, `APIRequestArgs`, `APIRequestOptions`, `APIResponse`, `QueryOrBody`, `ClientEvents`, `TypedEventEmitter`, `CollectionConstructor` | Supprimés (plomberie des requêtes, événements et `Collection`)                                 |

## Erreurs

```ts theme={"system"}
// v5
catch (e) { if (e.code === "RATE_LIMIT_EXCEEDED") ... }

// v6
catch (e) {
  if (e instanceof SquareCloudAPIError && e.status === 429) {
    console.log(e.code, e.message); // KEEP_CALM "Please wait 5 seconds..." or RATE_LIMITED
  }
}
```

* Les codes synthétiques ont disparu (`RATE_LIMIT_EXCEEDED`, `PAYLOAD_TOO_LARGE`, `SERVER_UNAVAILABLE`, `UNKNOWN_ERROR_<status>`) : c'est le vrai code de l'API qui remonte (`RATE_LIMITED`, `KEEP_CALM`, `DAILY_SNAPSHOTS_LIMIT_REACHED`, `FILE_TOO_LARGE`...).
* Aucune réponse : `status: 0` avec `NETWORK_ERROR` (la cause dans `cause`) ou `TIMEOUT`. Un corps sans code donne `UNKNOWN_ERROR` avec le vrai `status` et le message `HTTP <status>`.
* `instanceof TypeError` n'est plus vrai pour les erreurs de l'API.
* Une clé expirée donne 401 `ACCESS_DENIED`, comme une clé inconnue.
* Les erreurs de `ai.chat()`, authentification et limites de débit comprises, portent le code OpenAI en minuscules (`access_denied`, `rate_limit_exceeded`, ...).
* Un `start`/`stop`/`restart` refusé donne 409 avec uniquement un code : `CONTAINER_ALREADY_STARTED`, `CONTAINER_ALREADY_STOPPED`, `CONTAINER_TEMPORARILY_SUSPENDED`, `CONTAINER_NOT_FOUND`, `CONTAINER_INSUFFICIENT_DISK_SPACE`, `CONTAINER_NETWORK_CONFLICT` ou `ACTION_FAILED`.

## Changements de comportement

* Les appels expirent : 30 s par tentative par défaut (la v5 n'avait pas de timeout), au moins 120 s pour les appels que le serveur maintient ouverts. Définissez `timeoutMs: 0` pour n'en avoir aucun.
* `files.write()` traite une chaîne comme le contenu et l'envoie en texte brut ; les octets partent en base64, sans perte pour le binaire, et un contenu vide crée un fichier vide (même format de transmission que les SDKs Python et Go). `files.read()` demande du base64 et le décode.
* `files.list()` sur un répertoire manquant lève 404 `FILE_NOT_FOUND` au lieu de renvoyer `[]`.
* `snapshots.create()` renvoie `{ pending: true }` sur un 202 au lieu de lever une erreur.
* Les résultats de type chaîne ne sont jamais `undefined` : `setWebhook` et `resetCredentials("certificate")` renvoient `""` quand l'API n'envoie rien ; `deploys.current()` renvoie `{}`.
* `realtime()` se reconnecte en cas de connexion interrompue et sur `REALTIME_RECONNECT` (jusqu'à 3 fois d'affilée, au plus une ouverture toutes les 5,5 s).
* Nouvelles tentatives : erreurs réseau sur GET et 503 `UPLOAD_BUSY`/`ANALYTICS_BUSY` (plus `DATABASE_UNAVAILABLE` sur GET), avec backoff. Un 429 n'est jamais réessayé. `DATABASE_UNAVAILABLE` peut survenir après l'application d'une mutation : réessayez vous-même vos mutations idempotentes.
* Les identifiants vides, `.` et `..` échouent localement avec `INVALID_ID`.
* Les valeurs de requête `undefined`, `""` ou `false` ne sont pas envoyées.
