Entwickler

SDKs

Die Costfluent Public API aus Go, Python oder TypeScript aufrufen, mit einem Client, der Seiten liest, sicher wiederholt und Beträge exakt hält, und einem Token, das nur kann, was dein Skript braucht.

Costfluent veröffentlicht drei Clients für die Public API, quelloffen unter der Apache-2.0-Lizenz: costfluent-go für Go, costfluent-python für Python und costfluent-typescript für TypeScript. Die Clients für Python und TypeScript werden aus dem OpenAPI-Dokument der API erzeugt und decken jede Operation ab; der Go-Client ist von Hand geschrieben, und seine Tests halten seine typisierten Methoden an dasselbe Dokument. Alle drei senden dein API-Token als Bearer-Token, folgen den Seiten einer Liste, wiederholen, was sich gefahrlos wiederholen lässt, und geben Geldbeträge als exakte Dezimalzeichenketten weiter.

Bevor du beginnst

Enthalten im Pro-, Business- und Custom-Tarif. Tarife vergleichen

  • Das Token zu erstellen erfordert die Organisationsrolle Eigentümer, Integrationsverantwortliche Person oder Bearbeiter; siehe Authentifizierung bei der Public API.
  • Go ab 1.24, Python ab 3.11 oder Node.js ab 20. Der TypeScript-Client läuft überall, wo es fetch gibt, also auch in Deno, Bun und Edge-Runtimes.

Token erstellen

  1. Öffne Einstellungen, dann API-Token, und wähle API-Token erstellen.
  2. Gib einen Name ein, der sagt, welches Skript das Token nutzt, etwa Nächtlicher Budget-Export.
  3. Wähle unter Zugriff den Arbeitsbereich, in dem das Skript arbeitet, damit das Token nichts anderes erreicht. Behalte Gesamte Organisation nur, wenn das Skript mehrere Arbeitsbereiche liest.
  4. Wähle unter Vorlage die Vorlage Nur lesen, füge die Schreibberechtigungen hinzu, die das Skript braucht, und entferne jede Berechtigung, die es nicht aufruft. Die Beispiele auf dieser Seite brauchen Arbeitsbereiche anzeigen und, um einen Ordner anzulegen, Ordner erstellen.
  5. Wähle den Ablauf, etwa 90 Tage, und wähle API-Token erstellen.
  6. Kopiere das Token aus Ihr API-Token. Es wird nur einmal angezeigt.

Die Clients holen sich das Token nirgends selbst, dein Code übergibt es ihnen. Bewahre es in einer Umgebungsvariable oder einem Secret Store auf, nie im Quellcode, und lass den TypeScript-Client auf einem Server laufen: Ein Token in einem Browser-Bundle kann jeder lesen.

Client installieren

go get github.com/costfluent/costfluent-go

Das Go-Paket importierst du als github.com/costfluent/costfluent-go/costfluent.

Erster Aufruf

Jedes Beispiel liest das Token aus COSTFLUENT_API_TOKEN und listet alle Arbeitsbereiche, die das Token sieht.

package main import ( "context" "fmt" "log" "os" "github.com/costfluent/costfluent-go/costfluent" ) func main() { client := costfluent.NewClient(costfluent.WithAPIKey(os.Getenv("COSTFLUENT_API_TOKEN"))) ctx := context.Background() workspaces, err := client.ListAllWorkspaces(ctx, 100) if err != nil { log.Fatal(err) } for _, workspace := range workspaces { fmt.Println(workspace.ID, workspace.Name) } }

In Python ist jede Operation ein Modul unter costfluent.api mit den Funktionen sync und asyncio und ihren _detailed-Varianten, die zusätzlich Status und Header liefern; die Modelle liegen unter costfluent.models. In TypeScript sprichst du eine Operation über Methode und Pfad an, und Pfad, Query und Body sind aus der API typisiert. In Go ist jede Operation, die der Client abdeckt, eine Methode des Clients.

Alle Seiten lesen

Eine Liste antwortet seitenweise (Paginierung der Public API). Jeder Client liest die Seiten für dich:

  • Go: Eine paginierte Ressource hat eine ListAll-Methode, etwa ListAllWorkspaces(ctx, pageSize) oder ListAllBudgets(ctx, workspaceID, pageSize), die Seite um Seite anfragt, bis links.next leer ist. Die einfache Listenmethode liest mit PageOptions eine Seite und liefert deren Links.
  • Python: paginate nimmt eine erzeugte sync-Funktion mit ihren Argumenten und liefert jedes Element; apaginate macht dasselbe für eine asyncio-Funktion.
  • TypeScript: paginate nimmt eine Funktion, die den typisierten Aufruf macht und den übergebenen querySerializer weiterreicht, und liefert jedes Element.

Python und TypeScript folgen links.next und fragen die nächste Seite immer bei der Basis-URL des Clients an, sodass das Token nirgendwo anders hingeht.

Kostendaten aus einem Stand lesen

Landet eine Synchronisierung, während du Kostendaten seitenweise liest, kann eine spätere Seite eine Zeile wiederholen oder auslassen (Eine Synchronisierung zwischen den Seiten bemerken). Lies die erste Seite und sende ihre meta.dataVersion mit allen weiteren: DataVersion in CostDataQuery in Go, data_version in Python, dataVersion in TypeScript. paginate in Python und TypeScript behält sie von Seite zu Seite bei, weil links.next sie mitträgt.

query := &costfluent.CostDataQuery{ CostFilterOptions: costfluent.CostFilterOptions{StartDate: "2026-09-01", EndDate: "2026-09-30"}, } var rows []costfluent.CostDataPoint for query.Page = 1; ; query.Page++ { page, err := client.QueryCostData(ctx, query) if err != nil { log.Fatal(err) } rows = append(rows, page.Data...) if !page.Links.HasNextPage() { break } query.DataVersion = page.Meta.DataVersion }

Eine Seite, deren Daten eine Synchronisierung seit der ersten geändert hat, scheitert mit dem 409 der API: costfluent.IsConflict(err) in Go, ein CostfluentError mit dem code conflict in Python und TypeScript. Lies den Zeitraum dann ab Seite 1 neu.

Beträge bleiben exakt

Ein Geldbetrag kommt als die exakte Dezimalzeichenkette an, die die API schreibt, etwa "1250.50000000", nie als binäre Gleitkommazahl (Datenformate der Public API).

  • Go: Ein Betrag ist ein costfluent.Decimal. Equal und Cmp vergleichen zwei Beträge nach ihrem Wert, gleich mit wie vielen Nachkommastellen, Rat liefert den exakten Wert, und costfluent.ParseDecimal prüft einen Betrag, bevor du ihn sendest.
  • Python: Ein Betrag ist ein str. Wandle ihn mit decimal.Decimal(amount) um, wenn du damit rechnest.
  • TypeScript: Ein Betrag ist ein string. Lass ihn so, oder rechne mit einer Dezimalbibliothek.

Wiederholungen

Alle drei Clients wiederholen Anfragen selbst, nach denselben Regeln:

  • Ein 429 wird bei jeder Methode wiederholt, nach dem Retry-After oder RateLimit-Reset, den die API sendet (Rate Limits der Public API).
  • Ein 5xx, ein Verbindungsfehler oder ein 404, der nicht der Fehler-Body der API ist, sondern der eines Proxys, wird bei GET, HEAD, PUT, DELETE und beim Anlegen wiederholt. Andere POST-Anfragen, die Arbeit anstoßen wie eine Synchronisierung, werden nicht wiederholt, ebenso wenig eine Anfrage mit If-Match: Eine Anfrage erneut zu senden, die die API schon ausgeführt hat, könnte sie doppelt ausführen oder an ihrer eigenen Änderung scheitern.
  • Die Wartezeit wächst exponentiell ab einer Sekunde, mit Zufallsanteil, höchstens dreimal. Mit max_retries in Python und maxRetries in TypeScript änderst du die Anzahl.
  • Eine Wartezeit über 60 Sekunden bedeutet, dass das Anfragebudget des Tokens aufgebraucht ist: Der Aufruf scheitert sofort mit dem 429, statt abzuwarten.
  • Eine Anfrage, die in ein Timeout läuft, wird nicht wiederholt. Das Timeout beträgt 30 Sekunden, sofern du kein anderes setzt: WithTimeout in Go, timeout in Python, timeoutMs in TypeScript.

Anlegen ohne Duplikate

Jedes Anlegen sendet einen neuen Idempotency-Key und bei jeder Wiederholung denselben, sodass die API ein wiederholtes Anlegen mit ihrer ersten Antwort beantwortet, statt ein zweites Objekt anzulegen (Datenformate der Public API). In Python und TypeScript kannst du den Schlüssel selbst wählen, etwa damit ein Job, der kurz nach einem Fehler noch einmal läuft, den Ordner des ersten Laufs zurückbekommt; der Go-Client erzeugt seinen Schlüssel immer selbst.

folder, err := client.CreateFolder(ctx, &costfluent.CreateFolderInput{ WorkspaceID: "wsp_...", Title: "Finanzen", })

Einen Schlüssel, den die API schon mit einer anderen Anfrage gesehen hat, lehnt sie mit idempotency_key_reused ab: costfluent.IsIdempotencyKeyReused(err) in Go, is_idempotency_key_reused in Python und isIdempotencyKeyReused in TypeScript.

Versionen und API-Vertrag

Die drei Clients teilen sich eine Versionsnummer, 1.MINOR.PATCH; Go-Module schreiben sie mit einem führenden v. Die Hauptversion ist die Pfadversion der API, v1. Die Nebenversion steigt mit jedem Release, das einen neueren API-Vertrag enthält, und die Patch-Version ist eine Korrektur nur am Client.

Jeder Client trägt außerdem den SHA-256 des Public-API-Dokuments, aus dem er gebaut wurde: costfluent.ContractSHA256 in Go, costfluent.CONTRACT_SHA256 in Python und CONTRACT_SHA256, exportiert von @costfluent/sdk, in TypeScript. Zwei Clients mit demselben Hash wurden aus demselben Vertrag gebaut. Was sich in Version 1 der API ändern darf und was nicht, steht unter Versionierung der Public API.

Wie es sich verhält

  • Lehnt die API einen Aufruf ab, scheitert er nach den Wiederholungen mit dem Fehler der API: einem *costfluent.APIError in Go, einem CostfluentError in Python und TypeScript, jeweils mit dem Status und dem code der API (Fehler der Public API).
  • Der 404 eines Proxys, während die API neu startet, gilt nie als fehlendes Objekt: costfluent.IsNotFound(err) in Go, is_not_found in Python und isNotFound in TypeScript sind nur bei der eigenen Antwort der API wahr.
  • In Go nimmt eine arbeitsbereichsbezogene Methode eine Arbeitsbereichs-ID oder greift auf den Standard aus WithWorkspace zurück; ein Aufruf ohne beides scheitert, bevor er gesendet wird. Ein Workspace-Token liest nur seinen eigenen Arbeitsbereich, und die API lehnt jeden anderen ab.
  • Jeder Aufruf zählt gegen das Anfragelimit des Tokens.
  • Die Clients rufen https://api.costfluent.com auf, sofern du keine andere Basis-URL setzt.

Verwandte Seiten