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

# Migration zu v3

> Was sich zwischen dem Go SDK v2 und v3 geändert hat: ein Paket, ein konkreter *Client, ctx als erstes Argument, Ressourcengruppen, ein Fehlertyp, Timeouts und Wiederholungen. Eine Tabelle Methode für Methode.

v3 ist ein Breaking Release. Es verwendet ein einziges Paket, einen konkreten `*Client`, `ctx` überall als erstes Argument und Ressourcengruppen, und es behebt jeden bekannten Fehler von v2. Es deckt alle 67 Operationen der aktuellen API ab.

## Auf einen Blick

|                | v2                                                            | v3                                                                                                      |
| -------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Modul          | `.../v2` (Pakete `rest` + `squarecloud`)                      | `github.com/squarecloudofc/sdk-api-go/v3` (ein Paket)                                                   |
| Client         | `rest.New(rest.NewClient(key, ...))` (Interface)              | `squarecloud.New(key, ...Option)` (`*Client`)                                                           |
| Aufrufe        | `api.GetApplicationStatus(id, rest.WithContext(ctx))`         | `c.Apps.Status(ctx, id)`                                                                                |
| Fehler         | `*rest.APIError` mit `StatusCode`, Netzwerkfehler untypisiert | `*squarecloud.APIError` mit `Status`, `Code`, `Message`, `Method`, `Path` für alles                     |
| Timeouts       | `http.Client` mit festem `Timeout` von 30 s für alles         | Pro Aufruf über `ctx`; `WithTimeout`; Streams unbegrenzt                                                |
| Wiederholungen | Keine                                                         | Netzwerkfehler bei GET und 503 `UPLOAD_BUSY`/`ANALYTICS_BUSY`/`DATABASE_UNAVAILABLE` (`WithMaxRetries`) |
| Logging        | `WithLogger` (gab Secrets preis)                              | Keines                                                                                                  |
| Go             | 1.24                                                          | 1.22 oder neuer                                                                                         |
| Lizenz         | AGPL-3.0                                                      | MIT                                                                                                     |

## Konstruktion und Optionen

```diff theme={"system"}
-import (
-	"github.com/squarecloudofc/sdk-api-go/v2/rest"
-	"github.com/squarecloudofc/sdk-api-go/v2/squarecloud"
-)
-client := rest.NewClient(token, rest.WithUserAgent(ua), rest.WithLogger(logger))
-api := rest.New(client)
-defer client.Close()
+import "github.com/squarecloudofc/sdk-api-go/v3"
+
+c := squarecloud.New(token, squarecloud.WithUserAgent(ua))
```

```bash theme={"system"}
go get github.com/squarecloudofc/sdk-api-go/v3@v3.0.0
```

| v2                                                    | v3                                                                                                                             |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Pakete `rest` + `squarecloud`                         | Ein Paket `squarecloud` (Modul `.../v3`)                                                                                       |
| `rest.NewClient(token, opts...)` + `rest.New(client)` | `squarecloud.New(token, opts...)`                                                                                              |
| `rest.Rest` (Interface)                               | `*squarecloud.Client` (konkretes Struct). Um ihn zu mocken, deklariere dein eigenes kleines Interface oder verwende `httptest` |
| `rest.ConfigOpt`                                      | `squarecloud.Option`                                                                                                           |
| `rest.WithHTTPClient(hc)`                             | `squarecloud.WithHTTPClient(hc)`. Setze kein `hc.Timeout`: Es würde Realtime-Streams und Downloads abschneiden                 |
| `rest.WithURL(u)`                                     | `squarecloud.WithBaseURL(u)` (enthält weiterhin `/v2`)                                                                         |
| `rest.WithUserAgent(ua)`                              | `squarecloud.WithUserAgent(ua)`                                                                                                |
| `rest.WithLogger(l)`                                  | Entfernt: Das SDK loggt nie (v2 gab Secrets in Debug-Logs preis). Umhülle `hc.Transport`, um Anfragen zu verfolgen             |
| `client.Close()`, `client.HTTPClient()`               | Entfernt: Behalte deinen eigenen `*http.Client` und rufe darauf `CloseIdleConnections` auf                                     |
| `rest.APIURL`, `rest.APIVersion`, `rest.Endpoint*`    | Entfernt; `squarecloud.DefaultBaseURL` ist eine Konstante                                                                      |
| (keine)                                               | `squarecloud.WithMaxRetries(n)` (neu; Standard 2)                                                                              |
| Festes Timeout von 30 s im `http.Client`              | `squarecloud.WithTimeout(d)` (neu; Standard 30 s, `d <= 0` deaktiviert jede Standard-Deadline)                                 |

Optionen pro Anfrage:

| v2                                                                                      | v3                                                                                                                                                                                                 |
| --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rest.WithContext(ctx)`                                                                 | `ctx` ist das erste Argument jeder Methode                                                                                                                                                         |
| `rest.WithToken(token)` (z. B. um einen Schlüssel beim Login zu prüfen)                 | Erstelle einen Wegwerf-Client: `squarecloud.New(token).Account.Me(ctx)` (günstig, es werden keine Verbindungen gehalten)                                                                           |
| `rest.WithQueryParam("path", dir)` beim Commit                                          | `c.Apps.Commit(ctx, id, r, dir, "")`                                                                                                                                                               |
| `rest.WithQueryParam(filter, v)` bei Analytics                                          | `c.Apps.Network.Analytics(ctx, id, start, end, squarecloud.AnalyticsFilters{...})` mit `Country`, `IP`, `Path`, `Status`, `OS`, `Browser`, `Protocol`, `Referer`, `Provider`, `ContentType`, `Bot` |
| `rest.WithQueryParam("include_4xx", "true")`                                            | `c.Apps.Network.Errors(ctx, id, start, end, true)`                                                                                                                                                 |
| `rest.WithQueryParam("workspaceId", ws)` beim Status aller Apps                         | `c.Apps.StatusAll(ctx, ws)`                                                                                                                                                                        |
| `rest.WithHeader`, `rest.RequestOpt`, `rest.RequestConfig`, `rest.DefaultRequestConfig` | Entfernt                                                                                                                                                                                           |

## Methode für Methode

`api` ist das `rest.Rest` von v2, `c` der `*squarecloud.Client` von v3.

| v2                                                                                        | v3                                                                                                                 | Hinweise                                                                                                                                                                                                                                                                                   |
| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `api.SelfUser()`                                                                          | `me, err := c.Account.Me(ctx)`, dann `me.User`                                                                     | Gibt `Account` zurück                                                                                                                                                                                                                                                                      |
| `api.GetApplications()`                                                                   | `c.Account.Me(ctx)`, dann `me.Applications` (`[]AppSummary`)                                                       |                                                                                                                                                                                                                                                                                            |
| `api.GetDatabases()`                                                                      | `c.Account.Me(ctx)`, dann `me.Databases` (`[]DatabaseSummary`)                                                     |                                                                                                                                                                                                                                                                                            |
| `api.UserSnapshots(scope)`                                                                | `c.Account.Snapshots(ctx, scope)`                                                                                  |                                                                                                                                                                                                                                                                                            |
| `api.ServiceStatus()`                                                                     | `c.Service.Status(ctx)`                                                                                            | Neues Modell, siehe [Typen](#typen)                                                                                                                                                                                                                                                        |
| `api.PostApplications(r)` → `*ApplicationUploaded`                                        | `c.Apps.Create(ctx, r)` → `AppCreated` (ein Wert)                                                                  | v2 pufferte die ZIP im Speicher und benannte den Part `upload.zip`; v3 streamt sie und benennt den Part nach einer `*os.File` (ihrem Basisnamen), sonst `app.zip`. `Subdomain` gibt es nicht mehr: Lies `Domain`, den vollständigen Host (`my-app.squareweb.app`), `""` bei Nicht-Web-Apps |
| `api.GetApplication(id)`                                                                  | `c.Apps.Get(ctx, id)`                                                                                              |                                                                                                                                                                                                                                                                                            |
| `api.DeleteApplication(id)`                                                               | `c.Apps.Delete(ctx, id)`                                                                                           |                                                                                                                                                                                                                                                                                            |
| `api.PostApplicationSignal(id, squarecloud.ApplicationSignalStart/Stop/Restart)`          | `c.Apps.Start(ctx, id)` / `c.Apps.Stop(ctx, id)` / `c.Apps.Restart(ctx, id)`                                       |                                                                                                                                                                                                                                                                                            |
| `api.PostApplicationCommit(id, r, rest.WithQueryParam("path", p))`                        | `c.Apps.Commit(ctx, id, r, p, filename)`                                                                           | v2 benannte den Part immer `commit.zip`; v3 verwendet `filename`, sonst den eigenen Namen einer `*os.File`, sodass eine einzelne Nicht-ZIP-Datei jetzt unter ihrem eigenen Namen landet, statt als ZIP fehlzuschlagen                                                                      |
| `api.GetApplicationStatus(id)`                                                            | `c.Apps.Status(ctx, id)`                                                                                           |                                                                                                                                                                                                                                                                                            |
| `api.GetApplicationStatusRaw(id)`                                                         | `c.Apps.StatusRaw(ctx, id)`                                                                                        |                                                                                                                                                                                                                                                                                            |
| `api.GetApplicationListStatus()`                                                          | `c.Apps.StatusAll(ctx, "")`                                                                                        | Gibt `[]StatusListItem` zurück                                                                                                                                                                                                                                                             |
| `api.GetApplicationLogs(id)` → `ApplicationLogs`                                          | `c.Apps.Logs(ctx, id)` → `string`                                                                                  |                                                                                                                                                                                                                                                                                            |
| `api.GetApplicationMetrics(id)`                                                           | `c.Apps.Metrics(ctx, id)`                                                                                          | Die Punkte kommen mit dem neuesten zuerst, so wie die API sie sendet                                                                                                                                                                                                                       |
| `api.ApplicationRealtime(id, rest.WithContext(ctx))`                                      | `c.Apps.Realtime(ctx, id)`                                                                                         | Gibt `*Realtime` zurück; siehe [Verhaltensänderungen](#verhaltensänderungen)                                                                                                                                                                                                               |
| `api.GetApplicationDomains()`                                                             | `c.Apps.Domains(ctx)`                                                                                              |                                                                                                                                                                                                                                                                                            |
| `api.GetLoadBalancers()`                                                                  | `c.Apps.LoadBalancers(ctx)`                                                                                        |                                                                                                                                                                                                                                                                                            |
| `api.GetApplicationEnvs(id)`                                                              | `c.Apps.Envs.Get(ctx, id)`                                                                                         |                                                                                                                                                                                                                                                                                            |
| `api.SetApplicationEnvs(id, envs)`                                                        | `c.Apps.Envs.Set(ctx, id, envs)`                                                                                   |                                                                                                                                                                                                                                                                                            |
| `api.ReplaceApplicationEnvs(id, envs)`                                                    | `c.Apps.Envs.Replace(ctx, id, envs)`                                                                               |                                                                                                                                                                                                                                                                                            |
| `api.DeleteApplicationEnvs(id, keys)` → `error`                                           | `c.Apps.Envs.Delete(ctx, id, keys...)` → `(EnvVars, error)` (die verbleibenden Variablen)                          |                                                                                                                                                                                                                                                                                            |
| `api.GetApplicationFiles(id, path)` → `[]FileInfo`                                        | `c.Apps.Files.List(ctx, id, path)` → `[]FileEntry`                                                                 | Ein fehlendes Verzeichnis ergibt jetzt 404 `FILE_NOT_FOUND` (früher eine leere Liste); ein geschützter Pfad ergibt 403 `BLOCKED_PATH`                                                                                                                                                      |
| `api.ReadApplicationFile(id, path)` → `FileContent`                                       | `c.Apps.Files.Read(ctx, id, path)` → `[]byte`                                                                      | Als Base64 angefordert und dekodiert; eine Datei über 10 MB ergibt 413 `FILE_TOO_LARGE`                                                                                                                                                                                                    |
| `api.PutApplicationFile(id, path, b)` → `(FileWritten, error)`                            | `c.Apps.Files.Write(ctx, id, path, b)` → `error`. Entferne jede Prüfung auf `written`: Erfolg ist ein `nil`-Fehler | Der Inhalt wird immer Base64-kodiert gesendet, Binärdateien sind also sicher; leerer Inhalt schreibt eine leere Datei                                                                                                                                                                      |
| `api.MoveApplicationFile(id, from, to)`                                                   | `c.Apps.Files.Move(ctx, id, path, to)`                                                                             |                                                                                                                                                                                                                                                                                            |
| `api.DeleteApplicationFile(id, path)`                                                     | `c.Apps.Files.Delete(ctx, id, path)`                                                                               | Funktioniert jetzt (in v2 immer 400)                                                                                                                                                                                                                                                       |
| `api.GetApplicationSnapshots(id)`                                                         | `c.Apps.Snapshots.List(ctx, id)`                                                                                   | Jeder `Snapshot` enthält jetzt `VersionID` und `URL` (signierter Download-Link) von der API                                                                                                                                                                                                |
| `api.CreateApplicationSnapshot(id)`                                                       | `c.Apps.Snapshots.Create(ctx, id)`                                                                                 | Prüfe `.Pending` (202), bevor du `.URL` verwendest                                                                                                                                                                                                                                         |
| `api.RestoreApplicationSnapshot(id, snapID, verID)`                                       | `c.Apps.Snapshots.Restore(ctx, id, snap.Name, snap.VersionID)`                                                     | `VersionID` ist ein Feld, das die API sendet: Aus `Key` muss nichts mehr herausgeparst werden. Die Fehler findest du unter [Snapshots](/de/sdks/go/snapshots#snapshot-wiederherstellen)                                                                                                    |
| `api.GetApplicationDeployments(id)`                                                       | `c.Apps.Deploys.List(ctx, id)`                                                                                     |                                                                                                                                                                                                                                                                                            |
| `api.GetApplicationCurrentDeployment(id)`                                                 | `c.Apps.Deploys.Current(ctx, id)`                                                                                  |                                                                                                                                                                                                                                                                                            |
| `api.PostApplicationDeployWebhook(id, token)` → `GithubWebhook`                           | `c.Apps.Deploys.SetWebhook(ctx, id, token)` → `string`                                                             |                                                                                                                                                                                                                                                                                            |
| `api.LinkApplicationGithubApp(id, repo, branch)` → `GithubAppLink`                        | `c.Apps.Deploys.LinkGithubApp(ctx, id, repo, branch)` → `LinkedRepository`                                         | API-Schlüssel funktionieren jetzt (Scope `apps:deploy`); die Hülle `repository` entfällt; ein Konto ohne verbundenes GitHub ergibt 403 `GITHUB_NOT_CONNECTED`                                                                                                                              |
| `api.UnlinkApplicationGithubApp(id)`                                                      | `c.Apps.Deploys.UnlinkGithubApp(ctx, id)`                                                                          | 400 `GIT_NOT_CONFIGURED` ohne Verknüpfung                                                                                                                                                                                                                                                  |
| `api.GetApplicationDNS(id)`                                                               | `c.Apps.Network.DNS(ctx, id)`                                                                                      |                                                                                                                                                                                                                                                                                            |
| `api.SetApplicationCustomDomain(id, d)`                                                   | `c.Apps.Network.SetDomain(ctx, id, d)`                                                                             |                                                                                                                                                                                                                                                                                            |
| `api.GetApplicationAnalytics(id, s, e, opts...)`                                          | `c.Apps.Network.Analytics(ctx, id, s, e, squarecloud.AnalyticsFilters{...})`                                       | Gibt `*NetworkAnalytics` zurück, `nil` für ein Fenster ohne Verkehr                                                                                                                                                                                                                        |
| `api.GetApplicationNetworkErrors(id, s, e, opts...)`                                      | `c.Apps.Network.Errors(ctx, id, s, e, include4xx)`                                                                 | Gibt `*NetworkErrors` zurück, `nil`, wenn leer                                                                                                                                                                                                                                             |
| `api.GetApplicationNetworkLogs(id, s, e)`                                                 | `c.Apps.Network.Logs(ctx, id, s, e)`                                                                               |                                                                                                                                                                                                                                                                                            |
| `api.GetApplicationNetworkPerformance(id, s, e)`                                          | `c.Apps.Network.Performance(ctx, id, s, e)`                                                                        | Gibt `*NetworkPerformance` zurück, `nil`, wenn leer                                                                                                                                                                                                                                        |
| `api.PurgeApplicationCache(id)`                                                           | `c.Apps.Network.PurgeCache(ctx, id)`                                                                               |                                                                                                                                                                                                                                                                                            |
| `api.CreateDatabase(opts)`                                                                | `c.Databases.Create(ctx, squarecloud.DatabaseCreate{...})`                                                         |                                                                                                                                                                                                                                                                                            |
| `api.GetDatabase(id)`                                                                     | `c.Databases.Get(ctx, id)`                                                                                         |                                                                                                                                                                                                                                                                                            |
| `api.UpdateDatabase(id, opts)`                                                            | `c.Databases.Update(ctx, id, squarecloud.DatabaseUpdate{...})`                                                     |                                                                                                                                                                                                                                                                                            |
| `api.DeleteDatabase(id)`                                                                  | `c.Databases.Delete(ctx, id)`                                                                                      |                                                                                                                                                                                                                                                                                            |
| `api.StartDatabase(id)` / `api.StopDatabase(id)`                                          | `c.Databases.Start(ctx, id)` / `c.Databases.Stop(ctx, id)`                                                         |                                                                                                                                                                                                                                                                                            |
| `api.GetDatabaseStatus(id)` / `api.GetDatabaseStatusRaw(id)`                              | `c.Databases.Status(ctx, id)` / `c.Databases.StatusRaw(ctx, id)`                                                   |                                                                                                                                                                                                                                                                                            |
| `api.GetDatabaseListStatus()`                                                             | `c.Databases.StatusAll(ctx)`                                                                                       | Gibt `[]StatusListItem` zurück                                                                                                                                                                                                                                                             |
| `api.GetDatabaseMetrics(id)`                                                              | `c.Databases.Metrics(ctx, id)`                                                                                     |                                                                                                                                                                                                                                                                                            |
| `api.GetDatabaseCertificate(id)` → `DatabaseCertificate`                                  | `c.Databases.Certificate(ctx, id)` → `string` (Base64-PEM)                                                         |                                                                                                                                                                                                                                                                                            |
| `api.ResetDatabaseCredentials(id, t)` → `DatabasePasswordReset`                           | `c.Databases.ResetCredentials(ctx, id, t)` → `string`                                                              | Das neue Passwort, `""` beim Zurücksetzen des Zertifikats                                                                                                                                                                                                                                  |
| `api.GetDatabaseSnapshots` / `CreateDatabaseSnapshot` / `RestoreDatabaseSnapshot`         | `c.Databases.Snapshots.List` / `Create` / `Restore`                                                                | Wie bei Apps: Wiederherstellen mit `snap.Name` und `snap.VersionID`                                                                                                                                                                                                                        |
| `api.GetWorkspaces()`                                                                     | `c.Workspaces.List(ctx)`                                                                                           |                                                                                                                                                                                                                                                                                            |
| `api.GetWorkspace(id)`                                                                    | `c.Workspaces.Get(ctx, id)`                                                                                        |                                                                                                                                                                                                                                                                                            |
| `api.CreateWorkspace(name)`                                                               | `c.Workspaces.Create(ctx, name)`                                                                                   |                                                                                                                                                                                                                                                                                            |
| `api.DeleteWorkspace(id)`                                                                 | `c.Workspaces.Delete(ctx, id)`                                                                                     |                                                                                                                                                                                                                                                                                            |
| `api.LeaveWorkspace(id)`                                                                  | `c.Workspaces.Leave(ctx, id)`                                                                                      |                                                                                                                                                                                                                                                                                            |
| `api.AddWorkspaceMember(ws, code, group)`                                                 | `c.Workspaces.Members.Add(ctx, ws, code, group)`                                                                   |                                                                                                                                                                                                                                                                                            |
| `api.UpdateWorkspaceMember(ws, member, group)`                                            | `c.Workspaces.Members.Update(ctx, ws, member, group)`                                                              |                                                                                                                                                                                                                                                                                            |
| `api.RemoveWorkspaceMember(ws, member)`                                                   | `c.Workspaces.Members.Remove(ctx, ws, member)`                                                                     |                                                                                                                                                                                                                                                                                            |
| `api.GetWorkspaceInviteCode()` → `WorkspaceInviteCode`                                    | `c.Workspaces.Members.InviteCode(ctx)` → `string`                                                                  |                                                                                                                                                                                                                                                                                            |
| `api.AddWorkspaceApplication(ws, app)` / `RemoveWorkspaceApplication`                     | `c.Workspaces.Apps.Add(ctx, ws, app)` / `Remove`                                                                   |                                                                                                                                                                                                                                                                                            |
| Eine Snapshot-URL selbst herunterladen (`http.Get`)                                       | `c.DownloadSnapshot(ctx, url, w)`                                                                                  | Streamt in einen beliebigen `io.Writer`; sendet nie den Schlüssel                                                                                                                                                                                                                          |
| `rest.IsRateLimit(err)`                                                                   | `errors.As(err, &apiErr) && apiErr.Status == 429`                                                                  | Entfernt                                                                                                                                                                                                                                                                                   |
| `rest.ErrorCode(err)`                                                                     | `errors.As(err, &apiErr)`, dann `apiErr.Code`                                                                      | Entfernt                                                                                                                                                                                                                                                                                   |
| `client.Request(...)`, `client.Stream(...)` (`rest.Client`)                               | Die typisierten Methoden oben                                                                                      | Entfernt: Jede Operation hat ihre eigene Methode                                                                                                                                                                                                                                           |
| `rest.NewApplications(client)`, `rest.NewDatabases(client)`, `rest.NewWorkspaces(client)` | `squarecloud.New(key)`, dann die Felder `c.Apps`, `c.Databases`, `c.Workspaces`                                    | Entfernt                                                                                                                                                                                                                                                                                   |
| `rest.Applications`, `rest.Databases`, `rest.Workspaces` (Interfaces)                     | `squarecloud.AppsAPI`, `DatabasesAPI`, `WorkspacesAPI` (die Typen dieser Felder)                                   | Entfernt; deklariere dein eigenes Interface zum Mocken                                                                                                                                                                                                                                     |
| `rest.Config`, `rest.DefaultConfig()`, `(*rest.Config).Apply(opts)`                       | `squarecloud.New(key, opts...)` mit `WithHTTPClient`, `WithBaseURL`, `WithUserAgent`                               | Entfernt (verwende `Option`; es gibt keinen Logger)                                                                                                                                                                                                                                        |
| `(*rest.RequestConfig).Apply(opts)`                                                       | Übergib `ctx` und typisierte Argumente                                                                             | Entfernt                                                                                                                                                                                                                                                                                   |
| `(*rest.RealtimeStream).Next()` / `Close()`                                               | `(*squarecloud.Realtime).Next()` / `Close()`                                                                       | `Next` gibt nach `REALTIME_DISCONNECTED` `io.EOF` zurück                                                                                                                                                                                                                                   |
| (keine)                                                                                   | `c.AI.Chat(ctx, squarecloud.ChatRequest{...})`                                                                     | Neu                                                                                                                                                                                                                                                                                        |

## Typen

| v2 (`squarecloud.`)                                                                                                                                          | v3 (`squarecloud.`)                                                                                                                                                                                                                                                       |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `User` (aus `SelfUser`)                                                                                                                                      | `User` (innerhalb von `Account`, dem Ergebnis von `Account.Me`)                                                                                                                                                                                                           |
| `UserPlan`, `UserPlanMemory`                                                                                                                                 | `Plan`, `PlanMemory`. `Plan.Duration` ist der Ablaufzeitpunkt in Unix-**Millisekunden** (`*int64`, `nil`, wenn er nie abläuft): Wandle ihn mit `time.UnixMilli` um, nicht mit `time.Unix`                                                                                 |
| `UserApplication`, `UserDatabase` (`Type string`)                                                                                                            | `AppSummary`, `DatabaseSummary` (`Type DatabaseType`)                                                                                                                                                                                                                     |
| `Application`                                                                                                                                                | `App`                                                                                                                                                                                                                                                                     |
| `ApplicationUploaded` (`CPU int`), `ApplicationLanguage`                                                                                                     | `AppCreated` (`CPU float64`), `AppLanguage`                                                                                                                                                                                                                               |
| `ApplicationStatus`, `DatabaseStatus`                                                                                                                        | `RuntimeStats` (gemeinsam)                                                                                                                                                                                                                                                |
| `ApplicationStatusRaw`, `DatabaseStatusRaw`                                                                                                                  | `RuntimeStatsRaw`                                                                                                                                                                                                                                                         |
| `ApplicationStatusNetwork`, `ApplicationStatusNetworkRaw`                                                                                                    | `StatsNetwork`, `StatsNetworkRaw`                                                                                                                                                                                                                                         |
| `ApplicationStatusListItem`, `DatabaseStatusListItem`                                                                                                        | `StatusListItem`                                                                                                                                                                                                                                                          |
| `ApplicationLogs`                                                                                                                                            | `string`                                                                                                                                                                                                                                                                  |
| `ApplicationSignal*`                                                                                                                                         | Entfernt (verwende `Start`/`Stop`/`Restart`)                                                                                                                                                                                                                              |
| `FileInfo` (`Type FileType`, `LastModified int64`), Konstanten `FileType*`                                                                                   | `FileEntry` (`Type string`, `LastModified *float64`): `"file"`/`"directory"`; die API sendet Unix-ms mit Nachkommastellen oder `null`                                                                                                                                     |
| `FileContent`, `ByteArray`                                                                                                                                   | `[]byte`                                                                                                                                                                                                                                                                  |
| `FileWritten`                                                                                                                                                | Entfernt (undokumentiertes Feld)                                                                                                                                                                                                                                          |
| `Deployment` (`State DeploymentState`)                                                                                                                       | `DeployEvent` (`State`, `Source`, `Code`, `Message` als `string`). `Source` ist neu, immer `"git"`; ein `"error"`-Ereignis enthält `Code`, z. B. `CLONE_FAILED`, und manchmal `Message`                                                                                   |
| `DeploymentState*` (`DeploymentStateError` = `"error"`)                                                                                                      | String-Konstanten `Deploy*` (`DeployPending`, `DeployClone`, `DeployCommit`, `DeployRestarting`, `DeploySuccess`, `DeployError` = `"error"`)                                                                                                                              |
| `DeploymentFiles`, `DeploymentCurrent`, `DeploymentGithubApp`                                                                                                | `DeployFiles`, `DeployCurrent`, `DeployRepository`                                                                                                                                                                                                                        |
| `GithubWebhook`                                                                                                                                              | `string`                                                                                                                                                                                                                                                                  |
| `GithubAppLink`, `GithubAppRepository`                                                                                                                       | `LinkedRepository` mit `ID`, `FullName`, `Branch` (direkt zurückgegeben, ohne Hülle `Repository`)                                                                                                                                                                         |
| `Snapshot`                                                                                                                                                   | `Snapshot` + `VersionID`, `URL`, `Runtime`, `Origin` (alle Felder, die die API sendet)                                                                                                                                                                                    |
| `SnapshotCreated`                                                                                                                                            | `SnapshotCreated` + `Pending`                                                                                                                                                                                                                                             |
| `DatabaseType` mit `DatabaseTypeMongo`, `DatabaseTypeMySQL`, `DatabaseTypeRedis`, `DatabaseTypePostgres`                                                     | `DatabaseType` (unverändert) mit `DatabaseMongo`, `DatabaseMySQL`, `DatabaseRedis`, `DatabasePostgres` (Konstanten umbenannt)                                                                                                                                             |
| `DatabaseCreateOptions`, `DatabaseUpdateOptions`                                                                                                             | `DatabaseCreate`, `DatabaseUpdate`                                                                                                                                                                                                                                        |
| `DatabaseCreated` (`CPU int`, `Certificate string`)                                                                                                          | `DatabaseCreated` (`CPU float64`, `Certificate *string`, `nil`, wenn die API keines sendet)                                                                                                                                                                               |
| `DatabaseResetType`, `DatabaseResetPassword`, `DatabaseResetCertificate`                                                                                     | `DatabaseReset`, `ResetPassword`, `ResetCertificate`                                                                                                                                                                                                                      |
| `DatabaseCertificate`, `DatabasePasswordReset`                                                                                                               | `string`                                                                                                                                                                                                                                                                  |
| `WorkspaceMemberGroup`, `WorkspaceGroup*`                                                                                                                    | Eingabe: `WorkspaceGroup` (`GroupAdmin`, `GroupMaintain`, `GroupManager`, `GroupView`); `WorkspaceMember.Group` ist ein `string` (kann `"owner"` sein)                                                                                                                    |
| `WorkspaceMember` (`Name string`)                                                                                                                            | `WorkspaceMember` (`Name *string`, `nil`, wenn die API `null` sendet). Workspace-IDs sind 32 oder 40 Hex-Zeichen lang                                                                                                                                                     |
| `WorkspaceInviteCode`                                                                                                                                        | `string`                                                                                                                                                                                                                                                                  |
| `ServiceStatus` (`Status`, `Message`)                                                                                                                        | `ServiceStatus` (`Status`, `Message`, `CheckedAt`, `Stale`, `Services`, `Dependencies`). `Status` ist jetzt z. B. `"online"`; die Einträge sind `ServiceEntry`                                                                                                            |
| `rest.RealtimeStream`                                                                                                                                        | `*squarecloud.Realtime` (`Next`, `Close`)                                                                                                                                                                                                                                 |
| `RealtimeEvent` (`Event`, `Data`)                                                                                                                            | `RealtimeEvent` (`Event`, `Data`, `ID`, `Stream`, `Line`, `Status`)                                                                                                                                                                                                       |
| Query-Optionen bei Analytics                                                                                                                                 | `AnalyticsFilters` (ohne `Start`/`End`: Das sind Argumente)                                                                                                                                                                                                               |
| `NetworkErrorsSummaryClass` (`Class4xx`, `Class5xx`)                                                                                                         | `NetworkErrorsSummary.ByClass`, eine `map[string]int64` mit den Schlüsseln `"4xx"` und `"5xx"`                                                                                                                                                                            |
| `NetworkErrorsByStatus`, `NetworkErrorsTimeseries`, `NetworkErrorsTopPath`, `NetworkErrorsByMethod`                                                          | `NetworkErrorsStatus`, `NetworkErrorsBucket`, `NetworkErrorsPath`, `NetworkErrorsMethod`                                                                                                                                                                                  |
| `NetworkLatency`, `NetworkPerformance*`                                                                                                                      | `Percentiles` (`P50`/`P95`/`P99` sind `*float64`, `nil` für ein Fenster ohne Anfragen), `PerformanceSummary`, `PerformanceBucket`, `PerformanceRegion` (Länder und Colos; `P50`/`P95` `*float64`, `City`/`Country` `*string`), `PerformancePath` (`P95`/`P99` `*float64`) |
| `RealtimeStatus`                                                                                                                                             | `RealtimeStatus.CPULimit` ist eine Anzahl von Kernen (z. B. `1`, `0.5`)                                                                                                                                                                                                   |
| Provider-Werte in Analytics                                                                                                                                  | `"NAME (ASN)"` (z. B. `"GOOGLE (15169)"`); `AnalyticsFilters.Provider` nimmt genau diesen Wert                                                                                                                                                                            |
| `AppDomainType*`                                                                                                                                             | `AppDomain.Type` ist ein `string`                                                                                                                                                                                                                                         |
| `APIResponse[T]`                                                                                                                                             | Entfernt (intern)                                                                                                                                                                                                                                                         |
| `int`-Größen und -Zähler (`FileInfo.Size`, `Snapshot.Size`, `Visits`/`Requests` in Analytics, Summen und Maps der Netzwerkfehler, `Requests` in Performance) | `int64`                                                                                                                                                                                                                                                                   |

## Fehler

`rest.APIError` (`StatusCode`, `Code`, `Message`) wird zu `squarecloud.APIError` (`Status`, `Code`, `Message`, `Method`, `Path`): Benenne `StatusCode` in `Status` um. `rest.ErrorCode(err)` und `rest.IsRateLimit(err)` wurden entfernt: Verwende `errors.As` und prüfe `Code` oder `Status == 429`.

```go theme={"system"}
// v2
if rest.IsRateLimit(err) { ... }

// v3
var apiErr *squarecloud.APIError
if errors.As(err, &apiErr) && apiErr.Status == 429 {
	fmt.Println(apiErr.Code, apiErr.Message) // KEEP_CALM or RATE_LIMITED
}
```

* Netzwerkfehler sind jetzt `*APIError` mit `Status` `0`, `Code` `NETWORK_ERROR` oder `TIMEOUT` und dem Text der Ursache als `Message`, und sie lassen sich zur Ursache entpacken (`errors.Is(err, context.Canceled)` funktioniert).
* Ebenso lokale Prüfungen (`Status` `0`: `INVALID_ID`, `FILE_TOO_LARGE`, `INVALID_API_KEY`) und ein 2xx-Body, der kein JSON ist (`UNKNOWN_ERROR`, `Invalid JSON in HTTP <status> response`).
* Ein 2xx-Body mit `"status": "error"` ist jetzt ein Fehler (v2 meldete ihn als Erfolg). Die Ablehnungen des Clusters beim Starten/Stoppen von Apps und Datenbanken kommen als 409 `CONTAINER_ALREADY_STARTED`, `CONTAINER_ALREADY_STOPPED`, `CONTAINER_TEMPORARILY_SUSPENDED`, `CONTAINER_NOT_FOUND`, `CONTAINER_INSUFFICIENT_DISK_SPACE`, `CONTAINER_NETWORK_CONFLICT` oder `ACTION_FAILED`, ohne Nachricht. Das SDK gibt eine „bereits“-Antwort als Fehler zurück: Behandle sie selbst als Erfolg, wenn du das brauchst.
* Eine Antwort ohne Code hat den `Code` `UNKNOWN_ERROR`.
* Ein abgelaufener API-Schlüssel ergibt 401 `ACCESS_DENIED`, wie ein unbekannter.
* Es gibt eine `Code*`-Konstante für jeden Code, den die API dokumentiert. Die API sendet jetzt 429 `RATE_LIMITED` (`CodeRateLimited`), wo sie `RATE_LIMIT` und `RATE_LIMIT_EXCEEDED` sendete; `CodeRateLimit` und `CodeRateLimitExceeded` bleiben erhalten, als veraltet markiert.
* Jeder Fehler von `AI.Chat` hat die Form von OpenAI mit einem kleingeschriebenen Code (`access_denied`, `rate_limit_exceeded`, `server_overloaded`, ...), den `Code` unverändert enthält.
* `Error()` erzeugt `squarecloud: <METHOD> <path>: HTTP <status> <CODE>: <message>` (v2: `squarecloud: <message> (<CODE>, HTTP <status>)`). Prüfe die Felder, nicht den Text.

Die vollständige Referenz findest du unter [Fehler](/de/sdks/go/errors).

## Verhaltensänderungen

* **Leerer API-Schlüssel:** `New("")` (oder ein nur aus Leerzeichen bestehender Schlüssel) gibt weiterhin einen Client zurück (es kann keinen Fehler zurückgeben), aber jeder Aufruf außer `Service.Status` schlägt lokal mit `INVALID_API_KEY` fehl.
* **Snapshot 202:** v2 gab einen `*APIError` mit `StatusCode` 202 zurück. v3 gibt ein `SnapshotCreated` mit `Pending: true` und einen `nil`-Fehler zurück.
* **Realtime:** `Next` gibt jetzt ein `RealtimeEvent` zurück. Verzweige nach `ev.Event` (`system`, `status`, `logs`, `error`, `message`). Für Logs gib `ev.Line` aus (das Byte `\u0001`/`\u0002` wird entfernt; `ev.Data` bleibt der rohe Frame) und verwende `ev.Stream` für stdout/stderr. Für den Status verwende `ev.Status`: bei einem Status-Ereignis nie `nil`, flach über Frames und Neuverbindungen hinweg zusammengeführt. Nach `REALTIME_DISCONNECTED` gibt `Next` `io.EOF` zurück. Der Stream bricht nicht mehr nach 30 s ab, Neuverbindungen warten mindestens 5,5 s nach dem vorherigen Öffnen, und das Öffnen ist durch das Client-Timeout begrenzt, bis die Header eintreffen. Siehe [Realtime](/de/sdks/go/realtime).
* **Timeouts:** v2 verwendete für alles ein festes Timeout von 30 s im `http.Client`. v3 wendet eine Standard-Deadline nur an, wenn `ctx` keine hat: das Client-Timeout (`WithTimeout`, 30 s) für die meisten Aufrufe; mindestens 2 Minuten für Start/Stop/Restart, das Erstellen von Datenbanken, das Erstellen/Wiederherstellen von Snapshots und `AI.Chat`; keine für Uploads, Dateischreibvorgänge mit über 1 MiB Inhalt und Snapshot-Downloads. `WithTimeout(0)` deaktiviert sie alle.
* **Leere Netzwerkfenster:** `Analytics`, `Errors` und `Performance` geben `nil`-Zeiger zurück, wenn das Fenster keinen Verkehr hat.
* **Header:** Jede API-Anfrage sendet `Accept: application/json` (`text/event-stream` für Realtime). Der Standard-`User-Agent` hat sich von `Square GO` zu `squarecloud-sdk-go/3.0.0` geändert (`WithUserAgent` überschreibt ihn weiterhin).
* **IDs:** Jede ID wird jetzt als ein Pfadsegment prozentkodiert (v2 fügte sie unverändert in den Pfad ein), und eine leere ID, `.` oder `..` schlägt lokal mit `INVALID_ID` fehl.
* **Dateischreibvorgänge:** v2 sendete den Inhalt immer als String, was Binärdateien beschädigte, und konnte keine leere Datei schreiben. v3 sendet den Inhalt immer Base64-kodiert, sodass jedes Byte erhalten bleibt, leerer Inhalt eine leere Datei schreibt und Inhalt über 10 MB lokal mit `FILE_TOO_LARGE` fehlschlägt. Die API antwortet mit 400 `INVALID_CONTENT` auf Inhalt, den sie nicht dekodieren kann.
* **Dateilesevorgänge:** v3 fordert immer Base64 an und dekodiert es, statt des JSON-Byte-Arrays, das v2 las (und das die API als veraltet markiert hat). Eine Datei über 10 MB ergibt 413 `FILE_TOO_LARGE`.
* **Dateiauflistung:** Das Auflisten eines Verzeichnisses, das nicht existiert, ergibt 404 `FILE_NOT_FOUND`; früher war es eine leere Liste.
* **Snapshots:** Listeneinträge enthalten `VersionID` und `URL` von der API; aus `Key` wird nichts herausgeparst.
* **Wiederholungen:** neu. Netzwerkfehler bei GET, 503 `UPLOAD_BUSY`/`ANALYTICS_BUSY` und 503 `DATABASE_UNAVAILABLE` bei GET werden standardmäßig zweimal wiederholt; `WithMaxRetries(0)` stellt das Verhalten von v2 wieder her. `DATABASE_UNAVAILABLE` kann eintreffen, nachdem eine Mutation begonnen hat, daher wiederholt das SDK ihn bei anderen Methoden nie; wiederhole eine idempotente Mutation selbst, wenn du möchtest. Siehe [Wiederholungen](/de/sdks/go/errors#wiederholungen).
* **Go-Version:** Das Minimum ist von Go 1.24 auf Go 1.22 gesunken.
