> This page is for Plattform, version V4 (default).
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - V4 Experimental: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - Vorgängerversion: https://next.developer.frame.io/platform/v2/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://next.developer.frame.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://next.developer.frame.io/_mcp/server.

# Python SDK in Frame.io – Authentifizierungsleitfaden

In diesem Leitfaden wird erklärt, wie Sie sich mit der Frame.io-API über das **Python SDK in Frame.io** (`frameio`) authentifizieren.In der Frame.io V4-API wird der [Adobe Identity Management Service (IMS)](https://developer.adobe.com/developer-console/docs/guides/authentication/) genutzt, die OAuth-2.0-Identitätsplattform von Adobe.Dies ist eine eigenständige Referenz für Python-Entwickelnde.Alle unten stehenden Codebeispiele und Flüsse gelten ausschließlich für das `frameio`-Paket.

---

## Authentifizierungstypen im Python SDK

Im Python SDK werden vier Authentifizierungsoptionen unterstützt:

| Methode                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Anwendungsfall                                                                       | Benutzendeninteraktion? | Clientschlüssel erforderlich? |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | ----------------------- | ----------------------------- |
| **Statischer Token**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Schnelle Skripts, Tests oder Sie haben bereits einen Token                           | Nein                    | Nein                          |
| **Server-zu-Server**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Backend-Services, Cron-Jobs, Automatisierung                                         | Nein                    | Ja                            |
| **Web-Programm**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Serverseitige Apps (Flask, Django, FastAPI)                                          | Ja                      | Ja                            |
| **SPA (PKCE)**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | Browser-Apps, CLIs oder beliebige App, in der kein Schlüssel gespeichert werden kann | Ja                      | Nein                          |
| Durch **Server-zu-Server** kann Ihre App als Dienstkonto ohne Benutzendeninteraktion genutzt werden. Diese Funktion ist nur für Frame.io V4-Konten verfügbar, die über die [Adobe Admin Console](https://adminconsole.adobe.com/) verwaltet werden. Durch **Web App** und **SPA** kann Ihre App als bestimmter Benutzer bzw. bestimmte Benutzerin fungieren. Bei beiden wird im Hintergrund Adobe IMS verwendet: Benutzende autorisieren Ihre App, und der resultierende Code wird vom SDK gegen Token eingetauscht. Der `/authorize/v2`- und `/token/v3`-Fluss in IMS wird vom Python SDK übernommen. Für Web-Anwendungen benötigen Sie einen Clientschlüssel; für SPA verwenden Sie stattdessen [PKCE](https://datatracker.ietf.org/doc/html/rfc7636). |                                                                                      |                         |                               |

> **Note**
>
> Für [Anmeldedaten für Native Apps](https://developer.adobe.com/developer-console/docs/guides/authentication/UserAuthentication/implementation/#oauth-native-app-credential) von Adobe sind selbstdefinierte URI-Schema-Handler erforderlich (z. B. `adobe+<hash>://…</hash>`), mit denen Weiterleitungen auf Betriebssystemebene abgefangen werden. In Python gibt es keine standardmäßige Möglichkeit, solche Handler zu registrieren. Daher bietet das Python SDK auch keine `NativeAppAuth`-Klasse an. Nutzen Sie für Python-Apps mit Benutzendeninteraktion `WebAppAuth` mit einem lokalen Rückrufserver (z. B. Flask oder FastAPI). Verwenden Sie für nicht interaktive Arbeitslasten `ServerToServerAuth`.

---

## Dienstkonto-User

Bei der Server-zu-Server-Authentifizierung fungiert Ihre Anwendung als **Dienstkonto-User**, ein spezieller Kontotyp, mit dem im Namen des Services Aktionen durchgeführt werden können.Diese sind für andere Benutzende in Frame.io sichtbar: Wenn eine Aktion von einem Dienstkonto durchgeführt wird, wird dessen Name in der Bedienoberfläche angezeigt.Sie können dem Dienstkonto über die [Adobe Admin Console](https://adminconsole.adobe.com/) und die [Developer Console](https://developer.adobe.com/console) Zugriff gewähren und diesen widerrufen.Die Namen von Dienstkonten werden über die Frame.io-Bedienoberfläche verwaltet.Standardmäßig heißt Ihre erste S2S-Verbindung **Dienstkonto-User**, die zweite **Dienstkonto-User 2** und so weiter.

> **Info**
>
> Weitere Informationen finden Sie unter [Automatisieren Ihres Setups mit der Server-zu-Server-Unterstützung von Frame.io](https://helpx.adobe.com/enterprise/using/automate-using-frame-io.html).

---

## Schnellstart

### Voraussetzungen

1. **Anmeldedaten** von der [Adobe Developer Console](https://developer.adobe.com/console):

* **Client-ID:** Für alle OAuth-Flüsse erforderlich - **Clientschlüssel:** Für Server-zu-Server- und Web-App-Flüsse erforderlich - **Umleitungs-URI:** für Web-Anwendungs- und SPA-Flüsse erforderlich; muss in Ihrem Adobe-Projekt registriert sein

2. **SDK installieren:**

```bash
pip install frameio
```

### Auswählen einer Methode

* \*\*Keine Benutzenden beteiligt?\*\*Verwenden Sie **Server-zu-Server** (`ServerToServerAuth`).
* \*\*Benutzende beteiligt und Sie können einen Schlüssel speichern?\*\*Verwenden Sie **Web-Anwendung** (`WebAppAuth`).
* \*\*Benutzende beteiligt, aber Sie können keinen Schlüssel speichern?\*\*Verwenden Sie **SPA** (`SPAAuth`).

---

## Zugriffstoken

Falls Sie bereits über einen Zugriffstoken verfügen (aus einem anderen OAuth-System oder von einem vorherigen Austausch, z. B. über unseren [API-Explorer](/platform/api-reference/accounts/index?explorer=true)), können Sie ihn direkt übergeben:

```python
from frameio import Frameio

client = Frameio(token="YOUR_ACCESS_TOKEN")
```

Dies ist die einfachste Herangehensweise, aber der Token wird letztendlich ablaufen und wird nicht vom SDK aktualisiert.

### Ältere Entwicklungstoken

Bei V4-migrierten Konten, die noch nicht über die [Adobe Admin Console](https://adminconsole.adobe.com/) verwaltet werden, können Sie weiterhin ältere Entwicklungstoken von der [Frame.io-Entwickelnden-Website](https://developer.frame.io/app/tokens) verwenden.Sie müssen den Header `x-frameio-legacy-token-auth` einbeziehen und auf `true` setzen:

```python
from frameio import Frameio

client = Frameio(
    token="YOUR_LEGACY_DEVELOPER_TOKEN",
    headers={"x-frameio-legacy-token-auth": "true"},
)
```

Ältere Entwicklungstoken laufen nicht ab, sind aber ein Übergangsmechanismus.Für neue Integrationen und Produktionskapazität empfehlen wir die Verwendung einen der unten stehenden OAuth-2.0-Flüsse.Weitere Details finden Sie im [Migrationsleitfaden](/platform/docs/resources/migration#authentication).

---

## Server-zu-Server (Client-Anmeldedaten)

Verwenden Sie dies für Backend-Services und Skripte, die Zugriff auf Frame.io ohne Benutzendeninteraktion benötigen.Dieser Fluss ist nur für Frame.io V4-Konten verfügbar, die über die [Adobe Admin Console](https://adminconsole.adobe.com/) verwaltet werden.Deine Anwendung wird ohne menschliche Eingriffe als [Dienstkonto-User](#service-account-users) authentifiziert.

#### Synchron

```python
    from frameio import Frameio
    from frameio.auth import ServerToServerAuth

    auth = ServerToServerAuth(
        client_id="YOUR_CLIENT_ID",
        client_secret="YOUR_CLIENT_SECRET",
    )

    client = Frameio(token=auth.get_token)
```

#### Asynchron

```python
    from frameio import AsyncFrameio
    from frameio.auth import AsyncServerToServerAuth

    auth = AsyncServerToServerAuth(
        client_id="YOUR_CLIENT_ID",
        client_secret="YOUR_CLIENT_SECRET",
    )

    client = AsyncFrameio(token=auth.get_token)
```

Das ist alles.`auth.get_token` ist eine aufrufbare Funktion, die bei jeder Anfrage vom SDK aufgerufen wird.Wenn der aktuelle Token noch gültig ist, wird er sofort zurückgegeben.Wenn er kurz vor dem Ablauf steht, wird zuerst ein neuer Token abgerufen, völlig transparent.

### So funktioniert es

Ihre Client-Anmeldedaten (Client-ID und Schlüssel) **laufen niemals ab**.Sie rotieren sie lediglich manuell, aus Sicherheitsgründen.Durch S2S haben Sie praktisch permanenten, ununterbrochenen API-Zugriff ohne manuelle Eingriffe.

Unter der Haube:

1. Beim ersten API-Aufruf wird von `get_token` mithilfe des `client_credentials`-Grants ein neuer Zugriffstoken von Adobe IMS angefordert.
2. Der Token wird im Arbeitsspeicher zwischengespeichert.Einzelne Zugriffstoken laufen ab (in der Regel nach 24 Stunden), aber das wird für Sie gehandhabt.
3. Wenn ein zwischengespeicherter Token innerhalb des Aktualisierungspuffers liegt (Standard: 60 Sekunden vor Ablauf), wird vom SDK mit denselben Client-Anmeldedaten automatisch ein neuer abgerufen.
4. Es sind keine Aktualisierungstoken beteiligt.Die Client-Anmeldedaten selbst sind das langlebige Geheimnis, und sie können immer verwendet werden, um einen neuen Zugriffstoken zu prägen.

### Explizite Authentifizierung

Wenn Sie den Token frühzeitig abrufen möchten (zum Beispiel, um beim Start schnell mit ungültigen Anmeldedaten zu scheitern):

```python
auth = ServerToServerAuth(client_id="...", client_secret="...")
auth.authenticate()  # raises AuthenticationError if credentials are invalid
client = Frameio(token=auth.get_token)
```

---

## Web-Anwendung (Autorisierungscode)

Eignet sich für serverseitige Anwendungen, bei denen sich Benutzende mit ihrer Adobe ID anmelden.Für diesen Fluss ist ein Clientschlüssel erforderlich, der sicher auf Ihrem Server gespeichert werden muss.

#### Benutzende an Adobe IMS umleiten

#### Synchron

```python
    auth.refresh()  # fetches a new access token using the refresh token
```

#### Asynchron

```python
    await auth.refresh()
```

#### Rückruf verarbeiten

Wenn Benutzende von Adobe IMS wieder an Ihre `redirect-uri` zurückgeleitet werden, extrahieren Sie die Parameter `code` und `state`. Überprüfen Sie, ob der Status mit dem gespeicherten übereinstimmt, und tauschen Sie dann den Code gegen Token aus:

#### Synchron

```python
    auth.refresh()  # fetches a new access token using the refresh token
```

#### Asynchron

```python
    await auth.refresh()
```

Hiermit wird der Autorisierungscode gegen einen Zugriffstoken und einen Aktualisierungstoken ausgetauscht, und beide werden intern gespeichert.

#### Client verwenden

#### Synchron

```python
        from frameio import Frameio

        client = Frameio(token=auth.get_token)
```

#### Asynchron

```python
        from frameio import AsyncFrameio

        client = AsyncFrameio(token=auth.get_token)
```

Das ist alles.Von diesem Punkt an wird der Token-Lebenszyklus automatisch von `get_token` verwaltet.Wenn der Zugriffstoken kurz vor dem Ablauf steht, wird vom SDK mit dem Aktualisierungstoken ein neuer angefordert.Keine Benutzendeninteraktion erforderlich.

### Vollständiges Flask-Beispiel

```python
import secrets
from flask import Flask, redirect, request, session
from frameio import Frameio
from frameio.auth import WebAppAuth

app = Flask(__name__)
app.secret_key = secrets.token_bytes(32)

auth = WebAppAuth(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    redirect_uri="http://localhost:5000/callback",
)

@app.route("/login")
def login():
    state = secrets.token_urlsafe(32)
    session["oauth_state"] = state
    return redirect(auth.get_authorization_url(state=state))

@app.route("/callback")
def callback():
    if request.args.get("state") != session.pop("oauth_state", None):
        return "Invalid state parameter", 403

    auth.exchange_code(code=request.args["code"])

    client = Frameio(token=auth.get_token)
    accounts = client.accounts.index()
    return f"Authenticated — {len(accounts.data)} account(s) accessible."
```

---

## Single Page App / PKCE (Autorisierungscode und PKCE)

Dies ist für browserbasierte Anwendungen, Desktop-Anwendungen oder CLI-Tools vorgesehen, in denen ein Clientschlüssel nicht sicher gespeichert werden kann.In dem Fluss wird [PKCE (RFC 7636)](https://datatracker.ietf.org/doc/html/rfc7636) eingesetzt, um den Austausch des Autorisierungscodes zu schützen.

#### Autorisierungs-URL generieren

#### Synchron

```python
        from frameio.auth import SPAAuth

        auth = SPAAuth(
            client_id="YOUR_CLIENT_ID",
            redirect_uri="https://yourapp.com/callback",
        )

        import secrets
        state = secrets.token_urlsafe(32)

        result = auth.get_authorization_url(state=state)
        # result.url            -> redirect the user here
        # result.code_verifier  -> store this securely until the callback
```

#### Asynchron

```python
        from frameio.auth import AsyncSPAAuth

        auth = AsyncSPAAuth(
            client_id="YOUR_CLIENT_ID",
            redirect_uri="https://yourapp.com/callback",
        )

        # get_authorization_url is synchronous (no I/O needed)
        import secrets
        state = secrets.token_urlsafe(32)

        result = auth.get_authorization_url(state=state)
```

`Mit get_authorization_url` wird ein `AuthorizationUrlResult` zurückgegeben, das die vollständige URL (mit der eingebetteten PKCE `code_challenge`) und den `code_verifier` enthält, den Sie im nächsten Schritt benötigen.

#### Codes mittels Codeprüfer austauschen

Wenn Benutzende zurückgeleitet werden:

#### Synchron

```python
        auth.exchange_code(
            code="CODE_FROM_CALLBACK",
            code_verifier=result.code_verifier,
        )
```

#### Asynchron

```python
        await auth.exchange_code(
            code="CODE_FROM_CALLBACK",
            code_verifier=result.code_verifier,
        )
```

#### Client verwenden

#### Synchron

```python
        from frameio import Frameio

        client = Frameio(token=auth.get_token)
```

#### Asynchron

```python
        from frameio import AsyncFrameio

        client = AsyncFrameio(token=auth.get_token)
```

Das ist alles.Aktualisierung funktioniert genauso wie die Web-Anwendung – der Aktualisierungstoken wird automatisch vom SDK verwendet.Der Unterschied besteht darin, dass während der Aktualisierung kein Clientschlüssel gesendet wird, da der SPA-Fluss für öffentliche Clients konzipiert ist.

---

## Asynchrone Verwendung

Zu jeder Autorisierungsklasse gibt es ein asynchrones Gegenstück, dem das Präfix `Async` vorangestellt ist. Die obigen Codebeispiele enthalten die Registerkarten **Sync** und **Async**, wo zutreffend.

| Synchron                                                                                                                                                                                                      | Asynchron                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `ServerToServerAuth`                                                                                                                                                                                          | `AsyncServerToServerAuth` |
| `WebAppAuth`                                                                                                                                                                                                  | `AsyncWebAppAuth`         |
| `SPAAuth`                                                                                                                                                                                                     | `AsyncSPAAuth`            |
| Die API ist identisch.`get_authorization_url` bleibt synchron (keine E/A), während `exchange_code`, `refresh`, `revoke` und `get_token` alle `async` sind.Verwenden Sie die async-Klassen mit `AsyncFrameio`. |                           |

### Manuelle Aktualisierung der Token

Bei Web-Anwendungs- und SPA-Flüssen werden Token vom SDK automatisch über `get_token` aktualisiert.Falls Sie explizite Steuerung benötigen, können Sie `refresh()` direkt aufrufen:

#### Synchron

```python
    auth.refresh()  # fetches a new access token using the refresh token
```

#### Asynchron

```python
    await auth.refresh()
```

Das ist nützlich, wenn Sie vor einem wichtigen Vorgang eine Aktualisierung erzwingen möchten, anstatt sich auf den automatischen Aktualisierungspuffer zu verlassen.

---

## Token-Persistenz

`export_tokens()` und `import_tokens()` werden von allen Authentifizierungsklassen unterstützt, um den Tokenstatus auch nach Neustarts aufrechtzuerhalten.Für Web-Anwendungs- und SPA-Flüsse ist das besonders wichtig, da Zugriffs- und Aktualisierungstoken standardmäßig im Arbeitsspeicher gespeichert werden. Wenn Ihre Anwendung neu startet, müssten Benutzende sich erneut authentifizieren, es sei denn, Sie speichern die Token dauerhaft.Bei Server-zu-Server ist die Persistenz optional (es kann immer ein neuer Token mit den Anmeldedaten erstellt werden), doch durch das Importieren eines zwischengespeicherten Tokens wird ein zusätzlicher Umlauf beim Start vermieden.

### Exportieren und Importieren

```python
# After exchange_code(), save the token state
token_data = auth.export_tokens()
# token_data is a dict: {"access_token": "...", "refresh_token": "...", "expires_at": 1234567890.0}
# Save it to your database, file, or secret store

# On next startup, restore it
auth.import_tokens(token_data)
client = Frameio(token=auth.get_token)
# The SDK will automatically refresh if the token is near expiry
```

### Automatische Persistenz mit `on_token_refreshed`

Damit Token bei jeder Aktualisierung automatisch dauerhaft gespeichert werden, verwenden Sie den Rückruf `on_token_refreshed`:

```python
import json
from pathlib import Path

TOKEN_FILE = Path("tokens.json")

def save_tokens(tokens: dict):
    TOKEN_FILE.write_text(json.dumps(tokens))

auth = WebAppAuth(
    client_id="...",
    client_secret="...",
    redirect_uri="...",
    on_token_refreshed=save_tokens,
)

# On startup, restore if available
if TOKEN_FILE.exists():
    auth.import_tokens(json.loads(TOKEN_FILE.read_text()))
```

Der Rückruf erhält die gleiche dict-Form wie `export_tokens()` und wird nach jeder erfolgreichen Tokenaktualisierung ausgelöst. Für die asynchronen Klassen kann `on_token_refreshed` entweder eine reguläre Funktion oder eine `async`-Funktion sein.Beide werden unterstützt.

---

## Widerrufen von Token

So melden Sie Benutzende ab und machen deren Token mit Adobe IMS ungültig:

```python
auth.revoke()
```

Damit wird sowohl für den Zugriffstoken als auch für den Aktualisierungstoken eine bestmögliche Widerrufsanfrage an Adobe IMS gesendet. Anschließend wird der Status aller lokalen Token gelöscht.Nach dem Widerruf müssen Benutzende sich erneut authentifizieren.

> **Tip**
>
> Verwenden Sie bei den asynchronen Klassen `await auth.revoke()`.

---

## Fehlerbehandlung

Alle Authentifizierungsfehler übernehmen von `FrameioAuthError`, sodass Sie sie allgemein abfangen oder spezifische Fälle behandeln können:

```python
from frameio.auth import (
    FrameioAuthError,
    AuthenticationError,
    TokenExpiredError,
    ConfigurationError,
    NetworkError,
    RateLimitError,
)

try:
    auth.exchange_code(code="...")
except TokenExpiredError:
    # The refresh token has expired; redirect the user to sign in again
    pass
except AuthenticationError as e:
    # Token exchange failed
    print(f"Error: {e.error_code} - {e.error_description}")
except NetworkError:
    # Timeout or connection failure (after retries)
    pass
except RateLimitError as e:
    # 429 from Adobe IMS; retry after e.retry_after seconds
    pass
except FrameioAuthError:
    # Catch-all for any other auth error
    pass
```

### Fehlerreferenz

| Ausnahme              | Wann sie ausgelöst wird                                                                                   |
| --------------------- | --------------------------------------------------------------------------------------------------------- |
| `ConfigurationError`  | Fehlende oder ungültige Konfiguration (z. B. leere `client_id`, Nicht-HTTPS-Weiterleitungs-URI)           |
| `AuthenticationError` | Tokenaustausch oder -aktualisierung von Adobe IMS abgelehnt (hat `.error_code` und `.error_description`)  |
| `TokenExpiredError`   | Aktualisierungstoken selbst ist abgelaufen; Benutzende müssen sich erneut authentifizieren                |
| `NetworkError`        | HTTP-Timeout oder Verbindungsfehler nach allen Wiederholungsversuchen                                     |
| `RateLimitError`      | Von Adobe IMS wurde 429 zurückgegeben; sehen Sie zwecks Anleitung bzgl. Rückzug unter `.retry_after` nach |
| `PKCEError`           | PKCE-Verifizierung fehlgeschlagen (SPA-Fluss)                                                             |

### Umgang mit abgelaufenen Aktualisierungstoken in der Produktion

> **Warning**
>
> Bei Web-Anwendungs- und SPA-Flüssen läuft der Aktualisierungstoken irgendwann ab. Wenn das geschieht, wird von `get_token` ein `TokenExpiredError` ausgelöst.Diesen sollten Sie abfangen und Benutzende erneut durch den Autorisierungsfluss leiten.

```python
from frameio.auth import TokenExpiredError

try:
    client = Frameio(token=auth.get_token)
    assets = client.files.list(project_id="...")
except TokenExpiredError:
    # Clear persisted tokens and redirect user to login
    auth.revoke()
    return redirect("/login")
```

---

## Konfigurationsreferenz

Diese optionalen Parameter werden von allen Authentifizierungsklassen akzeptiert:

#### Parameterreferenz

| Parameter            | Standard                         | Beschreibung                                                                                                                                                                                                                                                 |
| -------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `scopes`             | Flussspezifische Standardwerte   | Durch Leerzeichen getrennte OAuth-Gültigkeitsbereiche.Bei S2S wird standardmäßig `openid AdobeID frame.s2s.all` verwendet; bei an Benutzenden orientierten Flüssen wird standardmäßig `openid email profile offline_access additional_info.roles` verwendet. |
| `ims_base_url`       | `https://ims-na1.adobelogin.com` | Basis-URL von Adobe IMS.Überschreibung für Staging- oder Nichtproduktionsumgebungen.                                                                                                                                                                         |
| `http_client`        | `None`                           | Selbstdefinierter `httpx.Client` (oder `httpx.AsyncClient`) für Proxy, mTLS oder Verbindungspooling.                                                                                                                                                         |
| `timeout`            | `30`                             | Timeout der HTTP-Anfrage in Sekunden für Token-Endpunkt-Aufrufe.                                                                                                                                                                                             |
| `max_retries`        | `2`                              | Maximale Anzahl von Wiederholungen für vorübergehende Fehler (5xx, Timeouts).Wiederholungen bei Ratenbegrenzungen (429) werden separat verfolgt.                                                                                                             |
| `refresh_buffer`     | `60`                             | Sekunden vor Ablauf des Tokens, um proaktive Aktualisierung auszulösen.                                                                                                                                                                                      |
| `on_token_refreshed` | `None`                           | Rückruf wird nach jeder erfolgreichen Tokenaktualisierung ausgelöst.Erhält ein dict (Wörterbuch) mit `access_token`, `refresh_token` und `expires_at`.                                                                                                       |

### Staging-Umgebungen

Zeigen Sie auf eine Staging-Instanz von Adobe IMS, indem Sie `ims_base_url` überschreiben.Vom SDK wird auch `DEFAULT_IMS_BASE_URL` (`https://ims-na1.adobelogin.com`) exportiert, falls Sie den Produktionswert programmgesteuert referenzieren müssen.

```python
auth = ServerToServerAuth(
    client_id="...",
    client_secret="...",
    ims_base_url="https://ims-na1-stg1.adobelogin.com",
)
```

### Selbstdefinierter HTTP-Client

Für Proxy-Unterstützung oder selbstdefinierte TLS-Konfiguration:

```python
import httpx

http_client = httpx.Client(
    proxy="http://corporate-proxy:8080",
    verify="/path/to/custom-ca-bundle.pem",
)

auth = ServerToServerAuth(
    client_id="...",
    client_secret="...",
    http_client=http_client,
)
```

---

## Thread-Sicherheit

Die synchronen Authentifizierungsklassen sind vollkommen Thread-sicher.Wenn `get_token` von mehreren Threads gleichzeitig aufgerufen wird und eine Aktualisierung erforderlich ist, wird die Aktualisierung nur von einem Thread durchgeführt.Die anderen warten und erhalten das gleiche Ergebnis.Es ist keine externe Sperrung erforderlich.Die asynchronen Klassen bieten mit `asyncio.Lock` dieselbe Garantie, sicher für gleichzeitige Koroutinen innerhalb einer einzelnen Ereignisschleife.