diff --git a/docs/api/sdks/python.mdx b/docs/api/sdks/python.mdx new file mode 100644 index 000000000..78514db94 --- /dev/null +++ b/docs/api/sdks/python.mdx @@ -0,0 +1,539 @@ +--- +title: Python SDK +sidebar_label: Python SDK +description: Guide how to use and install the Python SDK for the mittwald API, including client generation and maintenance. +--- + +## Quickstart {#quickstart} + +This guide shows how to get started with the mittwald API Python SDK. The example script demonstrates authentication and fetching server information. + +### 1. Installation {#installation} + +Ensure Python 3.10+ is available, then install the required packages: + +```shellsession +user@local $ pip install mittwald-api-client python-dotenv +``` + +- `mittwald-api-client` is the (generated) SDK. +- `python-dotenv` loads environment variables from a `.env` file. + +### 2. Prepare Credentials {#prepare-credentials} + +Create a file named `.env` in your project directory with the following content: + +``` +API_TOKEN=your-api-token +SERVER_ID=your-server-id +``` + +- Obtain the API token in the mittwald management UI. +- Set `SERVER_ID` to the UUID of a project or server you have access to. + +:::warning +Do not commit your `.env` file to source control; add it to `.gitignore`. +::: + +### 3. Usage Example {#usage-example} + +Save the following script as `api_client_test.py`: + +```python name=api_client_test.py +import os +import sys + +from dotenv import load_dotenv + +from mittwald_api_client import AuthenticatedClient +from mittwald_api_client.api.project import project_get_server + + +def main(): + """ + Test freshly built API client: set up authenticated client + from environment and fetch server information. + """ + + load_dotenv() + + API_TOKEN = os.getenv("API_TOKEN") + SERVER_ID = os.getenv("SERVER_ID") + + if API_TOKEN is None or SERVER_ID is None: + print("API_TOKEN or SERVER_ID missing. Check environment.") + sys.exit(1) + + client = AuthenticatedClient( + base_url="https://api.mittwald.de", + token=API_TOKEN, + follow_redirects=True, # mittwald API may return HTTP 308 redirects. + ) + + with client as myclient: + res = project_get_server.sync_detailed( + client=myclient, + server_id=SERVER_ID, + ) + + print("client call result:") + print(res) + print("---") + +if __name__ == '__main__': + main() +``` + +### 4. Run the Example {#run-example} + +Execute the script to perform an API call: + +```shellsession +(venv) user@local $ python api_client_test.py +``` + +- If the environment variables and token are valid, the script shows the result of the server info API call. +- If required variables are missing, the script exits with an explanatory message. + +--- + +### Next Steps {#next-steps} + +- Explore the SDK in more depth by reviewing the modules under `mittwald_api_client.api` and `mittwald_api_client.models`. +- For automation, overlays, and CI/CD, see the advanced guide. +- For complete API reference, consult the [mittwald OpenAPI specification](https://api.mittwald.de/v2/openapi.json). + +## Code generation – Python API Client {#example-python} + +**Requirements:** +- Python Installation (version 3.10+ recommended) +- Basic Bash, Python, `pip`, and virtual environment experience + +A Python API client can be generated using the [openapi-python-client module](https://github.com/openapi-generators/openapi-python-client). + +As the client itself is 100% generated, we focus on creating a **pipeline** for automated client creation, +release, and updates. Below, we start with the manual process for illustration—automation and maintenance +will be covered in the next section. + +### Creating a Python mittwald API Client {#create-python-client} + +Before automating the workflow, start by manually generating a client on your console. First, create your project folder, set up a Python virtual environment, and install the client generator and the dependency for loading environment variables: + +```shellsession +user@local $ mkdir python-api-client +user@local $ cd python-api-client +user@local $ python3 -m venv venv +user@local $ source venv/bin/activate +(venv) user@local $ pip install openapi-python-client python-dotenv +``` + +:::note +`(venv)` indicates your virtual environment is active. This alters your `PATH`, +so `python` points to the local interpreter. Activation for bash/zsh is shown; +for other shells (PowerShell, fish, etc.), see `venv/bin/`. Deactivate with `deactivate`. +On Windows, activation is `venv\Scripts\activate`. +::: + +#### Download the OpenAPI Specification {#fetch-openapi-specs} + +```shellsession +user@local $ curl --location --fail --silent 'https://api.mittwald.de/v2/openapi.json' > openapi.json +``` + +:::note +In order to avoid cluttering the generated client with too many operations, +it might be helpful to filter the openapi specification before generating +a client from it. This includes filtering deprecated operations, which otherwise +might show up in client as stubs. +::: + +#### (Optional) Adjust specification via overlays {#adjust-openapi-overlays} + +Although the raw OpenAPI specification can be used directly to create an API client, +often it is very useful to adjust the base specification in order to generate customized +clients. + +Overlays are declarative by definition, some logic might be required in order to +**generate** them depending on your use case. + +:::note +Overlays can be persisted for multiple usage and orchestration. Keep generated overlays +**and** base specification as build artifacts in order to create reproducible builds. + +Maintain descriptive titles for your overlays as well as good descriptions. This +will allow easier audits and bug tracking later down the line. +::: + +Here is an example snippet from an overlay: + +```json +{ + "overlay": "1.1.0", + "info": { + "title": "Overlay: Remove deprecated and unwanted operations", + "version": "1.0.0", + "description": "Removes deprecated operations and, if tags given, non-matching ops; deletes empty paths. See overlay_generator.py for business rule logic." + }, + "actions": [ + { + "target": "$.paths['/v2/appinstallations/{appInstallationId}/actions/{action}'].post", + "remove": true, + "description": "Removed due to deprecation or filter" + } + ] +} +``` + +The challenging part of creating overlays is finding correct [JSONPath](https://www.rfc-editor.org/rfc/rfc9535.pdf) +selectors in the `target` field of your `actions`. + +:::warning +The range of selectors available depends on the implementation of the patching +tool used! In other words: When using wider selectors matching more than one element, +there is a good chance the patching tool will only hit the first result! + +Prefer selectors matching exactly one element, be specific. Not only will this avoid subtle bugs +in the patching tools available, its explicit nature also helps to avoid side-effects and track +changes! That's why in most cases - especially when many operations need to be touched - such overlays +should be **constructed** from a script rather than written by hand. +::: + +Overlay application example using [oas-patcher](https://github.com/mcroissant/oas_patcher) + +```shellsession +# overlay generator creating "openapi_filter_overlay.json" +(venv) user@local $ python tools/overlay_generator.py openapi.json openapi_filter_overlay.json + +# apply overlay create "openapi_from_overlay.json" +(venv) user@local $ oas-patch overlay openapi.json openapi_filter_overlay.json -o openapi_from_overlay.json +``` + +The resulting `openapi_from_overlay.json` is now filtered according to actions defined +in `openapi_filter_overlay.json`. Keep those files bundled with base `openapi.json` in +order to reproduce the exact same build later. + +#### Run the Code Generator {#run-generator} + +```shellsession +(venv) user@local $ openapi-python-client generate --path ./openapi.json +``` + +The generator may emit warnings. +**How to handle warnings:** +- If your project needs the API parts triggering a warning, you must resolve the underlying issue. +- If you don’t need those endpoints or features, you can safely ignore the warnings. +- For blocking issues in the OpenAPI spec, please report them via the [mittwald feature requests tracker](https://github.com/mittwald/feature-requests). + +Keep maintenance effort low; avoid patching the OpenAPI spec unless strictly necessary. Prefer generator configuration tweaks. + +#### Install and test the Generated Client {#install-client} + +After generation, a `mittwald-api-client` folder will appear in your project directory. Install it for testing: + +```shellsession +(venv) user@local $ pip install -e ./mittwald-api-client +``` + +Review the generated `mittwald-api-client/README.md` to get started. Test your client with real business cases; here’s a starter script for a simple GET operation: + +```python name=examples/python-client-get.py +import os +import sys +from dotenv import load_dotenv +from mittwald_api_client import AuthenticatedClient +from mittwald_api_client.api.project import project_get_server + +def main(): + """Test freshly built API client: set up an authenticated client from environment and fetch server info.""" + load_dotenv() + API_TOKEN = os.getenv("API_TOKEN") + SERVER_ID = os.getenv("SERVER_ID") + if API_TOKEN is None or SERVER_ID is None: + print("API_TOKEN or SERVER_ID missing. Check environment.") + sys.exit(1) + client = AuthenticatedClient( + base_url="https://api.mittwald.de", + token=API_TOKEN, + follow_redirects=True, # API returns 308 redirects, not expected by client by default + ) + with client as myclient: + res = project_get_server.sync_detailed( + client=myclient, + server_id=SERVER_ID, + ) + print("client call result:") + print(res) + print("---") + +if __name__ == '__main__': + main() +``` + +:::note +It’s strongly recommended to manage credentials and context via environment variables or `.env` files, rather than command-line args or hardcoding. This example uses `dotenv.load_dotenv` to load credentials from `.env`. +::: + +```text +# Example .env file for local development +API_TOKEN=your-api-token-here +SERVER_ID=your-server-id-here +``` + +:::warning +Never commit `.env` or other secret files to version control. Use `.gitignore` files to exclude such files from version control. +::: + +:::note +For advanced or high-performance use cases, consider using the async API available in modern clients. +Start synchronous for simplicity; move to async as needed. +::: + +#### Testing Non-GET Operations – Example POST {#post-example} + +To use other HTTP methods (POST, PATCH, DELETE), you’ll need to construct request body objects. +Here’s an example of a POST operation: + +```python name=examples/python-client-post.py +import os +import sys +import time + +from dotenv import load_dotenv + +from mittwald_api_client import AuthenticatedClient +from mittwald_api_client.api.project import project_create_project +from mittwald_api_client.models import ProjectCreateProjectBody + + +def main(): + """ + Test fresh built API client, set up authenticated client + from environment and fetch server information + """ + + load_dotenv() + + API_TOKEN = os.getenv("API_TOKEN") + SERVER_ID = os.getenv("SERVER_ID") + + if API_TOKEN is None or SERVER_ID is None: + print("API_TOKEN or SERVER_ID missing. Check environment.") + sys.exit(1) + + client = AuthenticatedClient( + base_url="https://api.mittwald.de", + token=API_TOKEN, + follow_redirects=True, # API returns 308 aka permanent redirects, NOT expected by client by default + ) + + with client as myclient: + res = project_create_project.sync( + client=myclient, + server_id=SERVER_ID, + body=ProjectCreateProjectBody.from_dict({ + "description": f"python_post_test_project_{time.time()}" + }) + ) + + print("client call result:") + print(res) + print("---") + +if __name__ == '__main__': + main() +``` + +Check the generated client models for required fields and structures. + +:::note +Also make sure to use a token with write permissions when you apply CRUD operations via API. +::: + +### After Generation – Clean Up {#clean-up} + +- Review generated tests, README, and example scripts before publishing or integrating with your main app. +- Tidy up unneeded files so what you ship is clear and focused. + +### Package Naming – Note on Conflicts {#naming-conflicts} + +:::note +Generated package names (like `mittwald-api-client`) may collide with existing packages in PyPI. +If needed, adjust the generator config or package name before publishing to avoid conflicts. +::: + +### Publishing Python mittwald API Client {#publish-client} + +Publishing API clients depends on your use case; for highly specialized projects, publishing may not be needed. +For general or reusable clients, public PyPI is the standard. + +Follow instructions in the generated README for publishing. Example for **test PyPI**: + +```shellsession +(venv) user@local $ poetry config repositories.testpypi https://test.pypi.org/simple/ +(venv) user@local $ poetry config pypi-token.testpypi +(venv) user@local $ cd mittwald-api-client +(venv) user@local $ poetry publish --build -r testpypi +``` + +After successful publishing: + +```shellsession +(venv) user@local $ cd my-python-mittwald-project +(venv) user@local $ pip install -i https://test.pypi.org/simple/ mittwald-api-client +``` + +:::note +The same steps apply to productive PyPI. Use unique package names to avoid conflicts! +::: + +For automation and maintenance, please continue to the [maintenance & pipeline section](#maintenance-pipeline). + +### Automating Python API Client Generation and Release with GitHub Actions {#maintenance-pipeline} + +To ensure your Python mittwald API client always stays up-to-date with the latest API changes, +you can establish a CI/CD pipeline using GitHub Actions. This workflow will automatically +regenerate the client from the OpenAPI specification, test it, and—optionally—release new +versions on a regular schedule (e.g., weekly). + +#### Prerequisites {#pipeline-requirements} + +- Your project repository on GitHub. +- Python 3.10+ specified in your workflow. +- Access to the mittwald OpenAPI spec URL. +- Publishing credentials (e.g., PyPI token stored as GitHub repository secrets). + +#### Add Required Files to the Repo {#pipeline-config} + +- Place your generator config file (e.g., `.openapi-python-client-config.yml`) in the project root if needed. +- Keep your test scripts and sample `.env.example` files checked in, but **never** commit real credentials. + +#### Example GitHub Actions Workflow {#example-workflow} + +Create a file at `.github/workflows/client-release.yml`: + +```yaml name=.github/workflows/client-release.yml +name: API Client Regeneration and Release + +permissions: + contents: write + id-token: write # Required for OIDC with PyPI trusted publisher + +on: + schedule: + - cron: '0 4 * * 1' # Runs every Monday at 04:00 UTC + workflow_dispatch: # Allows manual trigger + +jobs: + build-and-release: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 # v4 is latest stable at time of writing + with: + fetch-depth: 0 # Fetch all history and tags + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Upgrade pip, install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements_build.txt + + - name: Download OpenAPI specification + run: curl --location --fail --silent 'https://api.mittwald.de/v2/openapi.json' > openapi.json + + - name: Filter deprecated endpoints from OpenAPI spec + run: | + echo "Filtering specs ..." + python tools/filter_openapi_deprecated.py openapi.json openapi.json + + - name: Set dynamic version in OpenAPI spec + run: | + LAST_TAG=$(git tag --sort=-creatordate | head -n 1) + python tools/adjust_openapi_version.py openapi.json $LAST_TAG + + - name: Regenerate Client + run: openapi-python-client generate --overwrite --path ./openapi.json + + - name: Install Generated Client for Testing + run: pip install -e ./mittwald-api-client + + - name: Run Tests + run: | + python smoke_test.py + + - name: Extract version from openapi.json + id: get_version + run: | + VERSION=$(jq -r '.info.version' openapi.json) + echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV + + - name: Commit regenerated client + run: | + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git add mittwald-api-client openapi.json + git commit -m "chore: update generated API client ${RELEASE_VERSION}" || echo "No changes to commit" + git push origin HEAD:${{ github.ref }} + + - name: Build Package + run: | + cd mittwald-api-client + poetry build + + - name: List build output + run: | + cd mittwald-api-client + ls -la dist + + - name: Publish to TestPyPI using OIDC + if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} + uses: pypa/gh-action-pypi-publish@v1.13.0 + with: + repository-url: https://test.pypi.org/legacy/ + packages-dir: mittwald-api-client/dist + verbose: true + + - name: Create and push git tag + if: success() + run: | + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git tag "v$RELEASE_VERSION" + git push origin "v$RELEASE_VERSION" + env: + RELEASE_VERSION: ${{ env.RELEASE_VERSION }} + + - name: Upload built packages for inspection + uses: actions/upload-artifact@v4 + with: + name: built-dist + path: mittwald-api-client/dist/ +``` + +#### Best Practices and Tips {#best-practices} + +- **Schedule wisely:** + Use the `cron` scheduling syntax to control how frequently releases occur (e.g., weekly, daily). +- **Secure secrets:** + Configure your workflow as trusted publisher on PyPI and use modern `gh-action-pypi-publish` action. + This is the up-to-date method to create secure and tokenless release pipelines. +- **Testing:** + Always test the regenerated client before publishing. Add meaningful business case tests to prevent releasing broken packages. +- **Manual triggers:** + The `workflow_dispatch` event allows maintainers to trigger releases as needed. +- **Version control:** + Consider tagging releases or updating version numbers based on API/spec changes. +- **Artifact upload:** + Add `upload-artifact` step to conserve build output for debugging and introspection. + +#### Extending the Workflow {#extend-workflow} + +- You can add steps to create release notes, tag versions, or manage changelogs automatically. +- Support multiple Python versions by matrix builds if needed. +- Integrate notifications or failed build alerts via Slack, email, etc. + +With this setup, your API client stays current, tested, and easily distributable—without manual intervention. diff --git a/docs/platform/development/api-clients.mdx b/docs/platform/development/api-clients.mdx new file mode 100644 index 000000000..10a9928bd --- /dev/null +++ b/docs/platform/development/api-clients.mdx @@ -0,0 +1,192 @@ +--- +title: Creating API clients +sidebar_label: Creating API clients +description: A guide on how to create API clients from OpenAPI specification +--- + +## Introduction {#intro} + +When working with the mittwald API, there are many reasons why you +might want—or even need—to build a custom API client, rather than +relying solely on official SDKs. While language preference and adherence +to company standards are common motivations, there are several additional +drivers worth considering: + +- **Programming Language and Technology Stack** + Not all languages or platforms have a first-party SDK. + If your project uses a language, framework, or environment not supported + out of the box, a custom client ensures smooth integration. + +- **Advanced or Non-Standard Authentication Flows** + Some projects require flexible ways to authenticate: using tokens from + environment variables, securing extension interactions, handling session + tokens in browser scenarios, or rotating secrets automatically. Official + clients might not cover new or complex organizational authentication needs. + +- **Integration in Specialized Environments** + From CLI tools to browser-based apps, serverless functions, or embedded systems, + platform and runtime constraints sometimes demand tailored clients optimized + for their specific environment. + +- **Adaptability to API Changes and Experimental Features** + APIs evolve—sometimes rapidly. Building your own client can help you leverage + beta features, work with endpoints not yet supported officially, or quickly + adapt to breaking changes or vendor extensions. + +- **Architectural and Integration Flexibility** + Teams with advanced architectural patterns (such as microservices, middleware layering, + or plug-in systems) often need more control, such as inserting custom logging, + tracing, or rate-limiting at the client level, or composing higher-level abstractions + on top of the API transport. + +- **Security, Compliance, and Auditing** + Certain industries and organizations require code to be fully auditable or self-hosted, + integrate tightly with internal security tooling, or manage credentials in custom ways. + Building your own client allows you to comply with these requirements. + +- **Testing, Mocking, and Local Development** + Custom clients can include features useful for local development and CI, such as mock + data modes, test doubles, or simplified authentication for early prototyping without + leaking sensitive credentials. + +- **Documentation, Localization, and Onboarding** + Sometimes, a custom client is a strategic asset: it can be written and documented in + the team’s native language, or tailored with onboarding examples and guides for your + organization’s developers. + +- **Dependency Management and Code Ownership** + Rolling your own client lets you pin dependencies, shape the API surface to your needs, + and avoid external drift—crucial for organizations with strict stability or security standards. + +**In summary:** +Custom API clients aren't just about personal or company preferences—they’re a key enabler +for integration, compliance, security, and developer productivity. + +By designing a client tailored to your specific requirements, you ensure your applications +remain robust, maintainable, and future-proof. + +## Preparations {#preparation} + +Thorough preparation sets the stage for a smooth and efficient custom API client development process. + +With the right groundwork, it’s often possible to generate most of your client automatically, +with minimal manual intervention. Below are key preparation areas to consider before you start: + +### Understand Your Use Case and Target Environment {#use-case-and-goal} + +- **Where will the client run?** + Identify if your client will be used in server-side apps, browser-based scripts, + command-line tools, serverless functions, or CI/CD pipelines. +- **Who are the end users?** + Consider internal teams, external customers, or automation tools, as this impacts features and + user-friendliness. +- **Any platform constraints?** + Some environments (like browser or serverless) might have restrictions on authentication methods, + storage, or dependencies. + +### Gather and Inspect the OpenAPI Specification {#get-openapi-specification} + +Download the current OpenAPI specification for the API: + +```shellsession +user@local $ curl --location --fail --silent 'https://api.mittwald.de/v2/openapi.json' > openapi.json +``` + +- **Validate the specification:** + Use OpenAPI validators (e.g., [Swagger Editor](https://editor.swagger.io/)) to check for errors or inconsistencies. +- **Check for completeness:** + Ensure all required endpoints, authentication flows, and schemas are documented. + +### Clarify Authentication and Security Requirements {#authentication-and-security} + +- **Authentication methods:** + Will your client need to support API tokens, OAuth2, extension secrets, or additional mechanisms? +- **Secret management:** + Make sure required tokens or secrets are available and can be injected securely (e.g., via env vars, config files, secure vaults). +- **Plan for secure storage:** + Never hard-code sensitive information in the client. + +### Select and Set Up Your Code Generation Tooling {#code-generator} + +- **Choose a code generator:** + Tools like [OpenAPI Generator](https://openapi-generator.tech/), + [Swagger Codegen](https://github.com/swagger-api/swagger-codegen), or + [Autorest](https://aka.ms/autorest) can scaffold clients in many languages. +- **Check compatibility:** + Ensure your chosen tool supports your preferred language and the OpenAPI version provided. +- **Install the generator:** + Set up the codegen toolkit and familiarize yourself with its options and configuration files. + +### Prepare Generator and Project Configuration {#code-generator-config} + +- **Adjust generator settings:** + Configure type mappings, serialization options, HTTP client selection, package naming, + and code style to match your project’s conventions. +- **Supporting files:** + Prepare configuration/templates for environment variables, CI scripts, documentation, and testing. +- **Versioning setup:** + Decide on how your client should reflect the API version—this aids consumers in knowing API compatibility. + +### Plan for API Evolution and Maintenance {#api-evolution-and-maintenance} + +- **Automate updates:** + Consider scripting the whole fetch-generate-test process, so your client stays up to date as the API evolves. +- **Monitor API changes:** + Subscribe to API changelogs, and be ready to re-generate and retest as the OpenAPI spec changes. +- **Handle breaking changes:** + Set up version control, and plan for how to manage client updates if/when the API structure is updated. + +### Identify Special API Features and Custom Logic {#custom-logic} + +- **Special endpoints:** + Note if the API includes pagination, file uploads, webhooks, long-running operations, + or other advanced patterns. Code generators may require extra configuration or manual + adjustments for these. +- **Error handling:** + Check for consistent error response formats and plan how the generated client should surface them. +- **Custom workflows:** + If certain business flows require composite or multi-step API interactions, + document these scenarios to extend the client after generation. + +By thoroughly preparing along these lines, not only will you accelerate the initial client build, +but you’ll also ensure your solution remains robust, secure, and maintainable as both your +codebase and the mittwald API evolve. + +--- + +### Customizing the OpenAPI Specification with Overlays {#openapi-overlays} + +[OpenAPI overlays](https://learn.openapis.org/overlay/) provide a powerful and maintainable way to customize API specifications before client code generation. + +Instead of manually changing the base OpenAPI specification (or patching generated clients), overlays allow you to define patch operations—such as removing unwanted endpoints or adjusting documentation—without modifying the original source. + +Key benefits include: + +- **Reproducible builds**: Maintain overlays as code to ensure everyone on the team generates clients against the same, reviewed set of spec changes. +- **Separation of concerns**: Keep base specification updates and your own customizations clearly separated and trackable. +- **Automation friendly**: Overlays can be applied in CI/CD pipelines to always generate up-to-date clients as the API evolves. +- **Maintainability**: Layer multiple overlays for different use cases (e.g. filter endpoints, add documentation, translate field descriptions). + +Actionable steps to use overlays: + +1. **Create an overlay**: Define your patch operations in a dedicated overlay file. +2. **Apply the overlay with a tool**: Use tools like [oas-patcher](https://github.com/mcroissant/oas_patcher) to combine the base spec and your overlay file into a generated, customized spec. +3. **Generate your client**: Run your preferred OpenAPI generator against this customized spec. + +:::tip +🌱 **Best practice:** Maintain your generation process and overlays, not the generated output. This discipline reduces technical debt and supports rapid, error-free prototyping. +::: + +**Contract completeness:** +As a safeguard, test that every `operationId` in your (possibly filtered) OpenAPI spec maps to a callable method in your generated client. This ensures your customization process doesn’t accidentally omit needed endpoints or break integration reliability. + +**Common pitfall:** +Try to avoid patching generated client code directly. Prefer controlling output by configuration or overlays, which are easier to maintain as the API evolves. + +--- + +### Next Steps {#next-steps} + +- See the language-specific guides for concrete, end-to-end examples (e.g., [Python SDK generation](/docs/v2/api/sdks/python)). +- Integrate overlays and automation in your CI/CD to keep all clients current. +- For advanced usage—such as multi-language support or deeply customized workflows—extend your overlays and codegen process as your requirements grow. diff --git a/i18n/de/docusaurus-plugin-content-docs/current/api/sdks/python.mdx b/i18n/de/docusaurus-plugin-content-docs/current/api/sdks/python.mdx new file mode 100644 index 000000000..771f6b1b8 --- /dev/null +++ b/i18n/de/docusaurus-plugin-content-docs/current/api/sdks/python.mdx @@ -0,0 +1,537 @@ +--- +title: Python SDK +sidebar_label: Python SDK +description: Anleitung zur Verwendung und Installation des Python SDK für die mittwald API, einschließlich Clientgenerierung und -wartung. +--- + +## Schnellstart {#quickstart} + +Diese Anleitung zeigt dir, wie du das mittwald API Python SDK verwendest. Das Beispielskript demonstriert Authentifizierung und das Abrufen von Server-Informationen. + +### 1. Installation {#installation} + +Stelle sicher, dass Python 3.10+ installiert ist, und installiere die benötigten Pakete: + +```shellsession +user@local $ pip install mittwald-api-client python-dotenv +``` + +- `mittwald-api-client` ist das generierte SDK. +- `python-dotenv` lädt Umgebungsvariablen aus einer `.env`-Datei. + +### 2. Zugangsdaten vorbereiten {#prepare-credentials} + +Lege im Projektverzeichnis eine Datei namens `.env` mit folgendem Inhalt an: + +``` +API_TOKEN=dein-api-token +SERVER_ID=deine-server-id +``` + +- Deinen API-Token findest du im mittwald Verwaltungsbereich. +- `SERVER_ID` ist die UUID eines Projekts oder Servers, auf den du Zugriff hast. + +:::warning +Die `.env`-Datei solltest du nicht ins Versionskontrollsystem aufnehmen; füge sie zu `.gitignore` hinzu. +::: + +### 3. Anwendungsbeispiel {#usage-example} + +Speichere das folgende Skript als `api_client_test.py`: + +```python name=api_client_test.py +import os +import sys + +from dotenv import load_dotenv + +from mittwald_api_client import AuthenticatedClient +from mittwald_api_client.api.project import project_get_server + + +def main(): + """ + Frisch generierten API-Client testen: Authentifizierten Client aus Umgebungsvariablen einrichten + und Server-Informationen abrufen. + """ + + load_dotenv() + + API_TOKEN = os.getenv("API_TOKEN") + SERVER_ID = os.getenv("SERVER_ID") + + if API_TOKEN is None or SERVER_ID is None: + print("API_TOKEN oder SERVER_ID fehlt. Bitte prüfe deine Umgebung.") + sys.exit(1) + + client = AuthenticatedClient( + base_url="https://api.mittwald.de", + token=API_TOKEN, + follow_redirects=True, # Die mittwald API kann HTTP 308 Redirects zurückgeben. + ) + + with client as myclient: + res = project_get_server.sync_detailed( + client=myclient, + server_id=SERVER_ID, + ) + + print("Antwort des Client-Calls:") + print(res) + print("---") + +if __name__ == '__main__': + main() +``` + +### 4. Beispiel ausführen {#run-example} + +Führe das Skript aus, um einen API-Aufruf zu machen: + +```shellsession +(venv) user@local $ python api_client_test.py +``` + +- Sind die Umgebungsvariablen und dein Token korrekt, zeigt das Skript das Ergebnis des API-Aufrufs. +- Fehlen benötigte Variablen, erscheint eine entsprechende Hinweismeldung. + +--- + +### Weitere Schritte {#next-steps} + +- Du kannst das SDK weiter erkunden, zum Beispiel über die Module `mittwald_api_client.api` und `mittwald_api_client.models`. +- Für Automatisierung, Overlays und CI/CD schau dir den erweiterten Leitfaden an. +- Die vollständige API-Dokumentation findest du in der [mittwald OpenAPI-Spezifikation](https://api.mittwald.de/v2/openapi.json). + +## Codegenerierung – Python API Client {#example-python} + +**Anforderungen:** +- Python-Installation (Version 3.10+ empfohlen) +- Grundkenntnisse in Bash, Python, `pip` und virtuellen Umgebungen + +Ein Python-API-Client kann mit dem [openapi-python-client-Modul](https://github.com/openapi-generators/openapi-python-client) generiert werden. + +Da der Client selbst zu 100% generiert wird, konzentrieren wir uns auf die Erstellung +einer **Pipeline** für automatisierte Client-Erstellung, Release und Updates. Im +Folgenden beginnen wir mit dem manuellen Prozess zur Veranschaulichung – Automatisierung +und Wartung werden im nächsten Abschnitt behandelt. + +### Einen Python mittwald API Client erstellen {#create-python-client} + +Bevor du den Workflow automatisierst, beginne damit, manuell einen Client in deiner +Konsole zu generieren. Erstelle zunächst deinen Projektordner, richte eine virtuelle +Python-Umgebung ein und installiere den Client-Generator: + +```shellsession +user@local $ mkdir python-api-client +user@local $ cd python-api-client +user@local $ python3 -m venv venv +user@local $ source venv/bin/activate +(venv) user@local $ pip install openapi-python-client python-dotenv +``` + +:::note +`(venv)` zeigt an, dass deine virtuelle Umgebung aktiv ist. Dies ändert deinen `PATH`, +sodass `python` auf den lokalen Interpreter zeigt. Die Aktivierung für bash/zsh wird +gezeigt; für andere Shells (PowerShell, fish, etc.) siehe `venv/bin/`. Deaktivierung +mit `deactivate`. Unter Windows ist die Aktivierung `venv\Scripts\activate`. +::: + +#### Die OpenAPI-Spezifikation herunterladen {#fetch-openapi-specs} + +```shellsession +user@local $ curl --location --fail --silent 'https://api.mittwald.de/v2/openapi.json' > openapi.json +``` + +:::note +Um zu vermeiden, dass der generierte Client mit zu vielen Operationen überladen wird, +kann es hilfreich sein, die OpenAPI-Spezifikation vor der Clientgenerierung zu filtern. +Dies umfasst das Filtern veralteter Operationen, die andernfalls im Client als Platzhalter erscheinen könnten. +::: + +#### (Optional) Spezifikation per Overlay anpassen {#adjust-openapi-overlays} + +Du kannst die rohe OpenAPI-Spezifikation direkt nutzen, um einen API-Client zu erstellen. +Oft ist es jedoch sinnvoll, die Spezifikation vorher anzupassen, +um den Client individueller zu gestalten. + +Da Overlays deklarativ sind, kann es je nach Anwendungsfall notwendig sein, +eigene Logik zu verwenden, um diese Overlays zu **generieren**. + +:::note +Overlays kannst du speichern und mehrfach oder in Kombination anwenden. +Bewahre sowohl die generierten Overlays **als auch** die Basis-Spezifikation als Build-Artefakte auf, +damit du später reproduzierbare Builds erstellen kannst. + +Vergib verständliche Titel für deine Overlays und beschreibe sie präzise. +Das erleichtert spätere Audits und die Fehlersuche. +::: + +Hier ein Beispiel für ein Overlay: + +```json +{ + "overlay": "1.1.0", + "info": { + "title": "Overlay: Entferne veraltete und unerwünschte Operationen", + "version": "1.0.0", + "description": "Entfernt veraltete Operationen und – falls Tags angegeben sind – nicht passende Operationen; löscht leere Pfade. Siehe overlay_generator.py für die Business-Logik." + }, + "actions": [ + { + "target": "$.paths['/v2/appinstallations/{appInstallationId}/actions/{action}'].post", + "remove": true, + "description": "Wurde wegen Veralterung oder Filter entfernt" + } + ] +} +``` + +Die Herausforderung beim Erstellen von Overlays ist es, die passenden [JSONPath](https://www.rfc-editor.org/rfc/rfc9535.pdf) +Selektoren für das `target`-Feld in den Aktionen zu bestimmen. + +:::warning +Wie viele und welche Selektoren genutzt werden können, hängt vom verwendeten Patch-Tool ab. +Wenn du einen breiten Selektor verwendest, der mehrere Elemente trifft, ist es möglich, +dass das Tool nur das erste Element anpasst. + +Wähle Selektoren, die exakt ein Element treffen, und sei dabei so spezifisch wie möglich. +Das hilft, Fehler und unerwünschte Nebenwirkungen bei Änderungen zu vermeiden. +Besonders bei vielen Anpassungen sollten Overlays mit einem Skript generiert werden und nicht von Hand. +::: + +Beispiel für das Anwenden eines Overlays mit [oas-patcher](https://github.com/mcroissant/oas_patcher): + +```shellsession +# Overlay-Generator erstellt "openapi_filter_overlay.json" +(venv) user@local $ python tools/overlay_generator.py openapi.json openapi_filter_overlay.json + +# Overlay anwenden, erstellt "openapi_from_overlay.json" +(venv) user@local $ oas-patch overlay openapi.json openapi_filter_overlay.json -o openapi_from_overlay.json +``` + +Die resultierende `openapi_from_overlay.json` ist entsprechend den im `openapi_filter_overlay.json` +definierten Aktionen gefiltert. Halte diese Dateien zusammen mit der Basis-`openapi.json` bereit, +um Builds später exakt reproduzieren zu können. + +#### Den Code-Generator ausführen {#run-generator} + +```shellsession +(venv) user@local $ openapi-python-client generate --path ./openapi.json +``` + +Der Generator kann Warnungen ausgeben. +**Wie mit Warnungen umgehen:** +- Wenn dein Projekt die API-Teile benötigt, die eine Warnung auslösen, musst du das zugrunde liegende Problem beheben. +- Wenn du diese Endpunkte oder Features nicht benötigst, kannst du die Warnungen sicher ignorieren. +- Für blockierende Probleme in der OpenAPI-Spezifikation melde diese bitte über den [mittwald Feature Requests Tracker](https://github.com/mittwald/feature-requests). + +Halte den Wartungsaufwand gering; vermeide es, die OpenAPI-Spezifikation zu patchen, es sei denn, es ist unbedingt notwendig. Bevorzuge Generator-Konfigurationsanpassungen. + +#### Den generierten Client installieren und testen {#install-client} + +Nach der Generierung erscheint ein `mittwald-api-client`-Ordner in deinem Projektverzeichnis. Installiere ihn zum Testen: + +```shellsession +(venv) user@local $ pip install -e ./mittwald-api-client +``` + +Schaue dir die generierte `mittwald-api-client/README.md` an, um loszulegen. Teste deinen Client mit echten Business Cases; hier ist ein Starter-Skript für eine einfache GET-Operation: + +```python name=examples/python-client-get.py +import os +import sys +from dotenv import load_dotenv +from mittwald_api_client import AuthenticatedClient +from mittwald_api_client.api.project import project_get_server + +def main(): + """Frisch generierten API-Client testen: Authentifizierten Client aus Umgebung einrichten und Server-Info abrufen.""" + load_dotenv() + API_TOKEN = os.getenv("API_TOKEN") + SERVER_ID = os.getenv("SERVER_ID") + if API_TOKEN is None or SERVER_ID is None: + print("API_TOKEN oder SERVER_ID fehlt. Bitte prüfe deine Umgebung.") + sys.exit(1) + client = AuthenticatedClient( + base_url="https://api.mittwald.de", + token=API_TOKEN, + follow_redirects=True, # Die mittwald API kann HTTP 308 Redirects zurückgeben, die der Client standardmäßig nicht erwartet + ) + with client as myclient: + res = project_get_server.sync_detailed( + client=myclient, + server_id=SERVER_ID, + ) + print("Ergebnis des Client-Calls:") + print(res) + print("---") + +if __name__ == '__main__': + main() +``` + +:::note +Es wird dringend empfohlen, Credentials und Kontext über Umgebungsvariablen oder `.env`-Dateien zu verwalten, anstatt über Kommandozeilen-Argumente oder Hardcoding. Dieses Beispiel verwendet `dotenv.load_dotenv`, um Credentials aus `.env` zu laden. +::: + +```text +# Example .env file for local development +API_TOKEN=your-api-token-here +SERVER_ID=your-server-id-here +``` + +:::warning +Committe niemals `.env` oder andere Secret-Dateien in die Versionskontrolle. Verwende `.gitignore`-Dateien, um solche Dateien von der Versionskontrolle auszuschließen. +::: + +:::note +Für fortgeschrittene oder leistungsintensive Anwendungsfälle erwäge die Verwendung der Async-API, die in modernen Clients verfügbar ist. Beginne synchron für Einfachheit; wechsle zu async, wenn nötig. +::: + +#### Nicht-GET-Operationen testen – Beispiel POST {#post-example} + +Um andere HTTP-Methoden (POST, PATCH, DELETE) zu verwenden, musst du Request-Body-Objekte konstruieren. Hier ist ein Beispiel für eine POST-Operation: + +```python name=examples/python-client-post.py +import os +import sys +import time + +from dotenv import load_dotenv + +from mittwald_api_client import AuthenticatedClient +from mittwald_api_client.api.project import project_create_project +from mittwald_api_client.models import ProjectCreateProjectBody + + +def main(): + """ + Frisch generierten API-Client testen: Authentifizierten Client aus Umgebung + einrichten und Server-Informationen abrufen + """ + + load_dotenv() + + API_TOKEN = os.getenv("API_TOKEN") + SERVER_ID = os.getenv("SERVER_ID") + + if API_TOKEN is None or SERVER_ID is None: + print("API_TOKEN oder SERVER_ID fehlt. Bitte prüfe deine Umgebung.") + sys.exit(1) + + client = AuthenticatedClient( + base_url="https://api.mittwald.de", + token=API_TOKEN, + follow_redirects=True, # API kann 308 aka permanente Redirects zurückgeben, die der Client standardmäßig NICHT erwartet + ) + + with client as myclient: + res = project_create_project.sync( + client=myclient, + server_id=SERVER_ID, + body=ProjectCreateProjectBody.from_dict({ + "description": f"python_post_test_project_{time.time()}" + }) + ) + + print("Ergebnis des Client-Calls:") + print(res) + print("---") + +if __name__ == '__main__': + main() +``` + +Prüfe die generierten Client-Modelle auf erforderliche Felder und Strukturen. + +:::note +Stelle auch sicher, dass du ein Token mit Schreibberechtigungen verwendest, wenn du CRUD-Operationen über die API ausführst. +::: + +### Nach der Generierung – Aufräumen {#clean-up} + +- Überprüfe generierte Tests, README und Beispiel-Skripte, bevor du publizierst oder mit deiner Haupt-App integrierst. +- Räume nicht benötigte Dateien auf, damit klar und fokussiert ist, was du auslieferst. + +### Package Naming – Hinweis zu Konflikten {#naming-conflicts} + +:::note +Generierte Package-Namen (wie `mittwald-api-client`) können mit bestehenden Packages in PyPI kollidieren. Bei Bedarf passe die Generator-Config oder den Package-Namen vor der Veröffentlichung an, um Konflikte zu vermeiden. +::: + +### Python mittwald API Client veröffentlichen {#publish-client} + +Die Veröffentlichung von API-Clients hängt von deinem Use Case ab; für hochspezialisierte Projekte ist eine Veröffentlichung möglicherweise nicht erforderlich. Für allgemeine oder wiederverwendbare Clients ist das öffentliche PyPI der Standard. + +Folge den Anweisungen in der generierten README für die Veröffentlichung. Beispiel für **test PyPI**: + +```shellsession +(venv) user@local $ poetry config repositories.testpypi https://test.pypi.org/simple/ +(venv) user@local $ poetry config pypi-token.testpypi +(venv) user@local $ cd mittwald-api-client +(venv) user@local $ poetry publish --build -r testpypi +``` + +Nach erfolgreicher Veröffentlichung: + +```shellsession +(venv) user@local $ cd my-python-mittwald-project +(venv) user@local $ pip install -i https://test.pypi.org/simple/ mittwald-api-client +``` + +:::note +Die gleichen Schritte gelten für das produktive PyPI. Verwende eindeutige Package-Namen, um Konflikte zu vermeiden! +::: + +Für Automatisierung und Wartung fahre bitte mit dem [Wartungs- & Pipeline-Abschnitt](#maintenance-pipeline) fort. + +### Python API Client-Generierung und -Release mit GitHub Actions automatisieren {#maintenance-pipeline} + +Um sicherzustellen, dass dein Python mittwald API Client immer auf dem neuesten Stand +mit den neuesten API-Änderungen bleibt, kannst du eine CI/CD-Pipeline mit GitHub Actions +einrichten. Dieser Workflow wird automatisch den Client aus der OpenAPI-Spezifikation +regenerieren, testen und – optional – neue Versionen nach einem regelmäßigen Zeitplan +(z. B. wöchentlich) veröffentlichen. + +#### Voraussetzungen {#pipeline-requirements} + +- Dein Projekt-Repository auf GitHub. +- Python 3.10+ in deinem Workflow spezifiziert. +- Zugang zur mittwald OpenAPI-Spezifikations-URL. +- Publishing-Credentials (z. B. PyPI-Token) als GitHub-Repository-Secrets gespeichert. + +#### Erforderliche Dateien zum Repo hinzufügen {#pipeline-config} + +- Platziere deine Generator-Config-Datei (z. B. `.openapi-python-client-config.yml`) im Projekt-Root, falls erforderlich. +- Behalte deine Test-Skripte und Beispiel-`.env.example`-Dateien eingecheckt, aber committe **niemals** echte Credentials. + +#### Beispiel GitHub Actions Workflow {#example-workflow} + +Erstelle eine Datei unter `.github/workflows/client-release.yml`: + +```yaml name=.github/workflows/client-release.yml +name: API Client Regeneration and Release + +permissions: + contents: write + id-token: write # Required for OIDC with PyPI trusted publisher + +on: + schedule: + - cron: '0 4 * * 1' # Runs every Monday at 04:00 UTC + workflow_dispatch: # Allows manual trigger + +jobs: + build-and-release: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 # v4 is latest stable at time of writing + with: + fetch-depth: 0 # Fetch all history and tags + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Upgrade pip, install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements_build.txt + + - name: Download OpenAPI specification + run: curl --location --fail --silent 'https://api.mittwald.de/v2/openapi.json' > openapi.json + + - name: Filter deprecated endpoints from OpenAPI spec + run: | + echo "Filtering specs ..." + python tools/filter_openapi_deprecated.py openapi.json openapi.json + + - name: Set dynamic version in OpenAPI spec + run: | + LAST_TAG=$(git tag --sort=-creatordate | head -n 1) + python tools/adjust_openapi_version.py openapi.json $LAST_TAG + + - name: Regenerate Client + run: openapi-python-client generate --overwrite --path ./openapi.json + + - name: Install Generated Client for Testing + run: pip install -e ./mittwald-api-client + + - name: Run Tests + run: | + python smoke_test.py + + - name: Extract version from openapi.json + id: get_version + run: | + VERSION=$(jq -r '.info.version' openapi.json) + echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV + + - name: Commit regenerated client + run: | + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git add mittwald-api-client openapi.json + git commit -m "chore: update generated API client ${RELEASE_VERSION}" || echo "No changes to commit" + git push origin HEAD:${{ github.ref }} + + - name: Build Package + run: | + cd mittwald-api-client + poetry build + + - name: List build output + run: | + cd mittwald-api-client + ls -la dist + + - name: Publish to TestPyPI using OIDC + if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} + uses: pypa/gh-action-pypi-publish@v1.13.0 + with: + repository-url: https://test.pypi.org/legacy/ + packages-dir: mittwald-api-client/dist + verbose: true + + - name: Create and push git tag + if: success() + run: | + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git tag "v$RELEASE_VERSION" + git push origin "v$RELEASE_VERSION" + env: + RELEASE_VERSION: ${{ env.RELEASE_VERSION }} + + - name: Upload built packages for inspection + uses: actions/upload-artifact@v4 + with: + name: built-dist + path: mittwald-api-client/dist/ +``` + +#### Best Practices und Tipps {#best-practices} + +- **Zeitplan weise wählen:** + Verwende die `cron`-Scheduling-Syntax, um zu steuern, wie häufig Releases stattfinden (z. B. wöchentlich, täglich). +- **Secrets sichern:** + Konfiguriere deinen Workflow als Trusted Publisher auf PyPI und verwende die moderne `gh-action-pypi-publish`-Action. Dies ist die aktuelle Methode, um sichere und tokenlose Release-Pipelines zu erstellen. +- **Testing:** + Teste den regenerierten Client immer vor der Veröffentlichung. Füge aussagekräftige Business-Case-Tests hinzu, um zu verhindern, dass defekte Packages veröffentlicht werden. +- **Manuelle Trigger:** + Das `workflow_dispatch`-Event ermöglicht es Maintainern, Releases bei Bedarf auszulösen. +- **Versionskontrolle:** + Erwäge, Releases zu taggen oder Versionsnummern basierend auf API-/Spec-Änderungen zu aktualisieren. +- **Artifact-Upload:** + Füge einen `upload-artifact`-Schritt hinzu, um Build-Output für Debugging und Inspektion zu bewahren. + +#### Den Workflow erweitern {#extend-workflow} + +- Du kannst Schritte hinzufügen, um automatisch Release Notes, Tags oder Changelogs zu erstellen. +- Unterstütze mehrere Python-Versionen durch Matrix-Builds, falls erforderlich. +- Integriere Benachrichtigungen oder Fehlschlag-Alarme über Slack, E-Mail, etc. + +Mit diesem Setup bleibt dein API-Client aktuell, getestet und einfach verteilbar – ohne manuelle Intervention. diff --git a/i18n/de/docusaurus-plugin-content-docs/current/platform/development/api-clients.mdx b/i18n/de/docusaurus-plugin-content-docs/current/platform/development/api-clients.mdx new file mode 100644 index 000000000..fe0983a7c --- /dev/null +++ b/i18n/de/docusaurus-plugin-content-docs/current/platform/development/api-clients.mdx @@ -0,0 +1,161 @@ +--- +title: API-Clients erstellen +sidebar_label: API-Clients erstellen +description: Guide für die Erstellung eigener API-Clients aus der OpenAPI-Spezifikation +--- + +## Einführung {#intro} + +Beim Arbeiten mit der mittwald API gibt es viele Gründe, warum du +einen eigenen API-Client entwickeln möchtest oder sogar musst – und nicht +nur auf die offiziellen SDKs zurückgreifst. Neben der Sprache oder internen +Vorgaben spielen weitere Faktoren eine wichtige Rolle: + +- **Programmiersprache und Technologie-Stack** + Nicht für alle Sprachen oder Plattformen gibt es ein offizielles SDK. + Mit einem eigenen Client kannst du jede Umgebung reibungslos anbinden. + +- **Spezielle oder erweiterte Authentifizierungsanforderungen** + Manchmal werden Authentifizierungsarten gebraucht, die die offiziellen Clients nicht bieten – etwa Token aus Umgebungsvariablen, Anbindung spezieller Security-Flows, Handling von Session-Tokens für Browser-Apps oder automatische Rotation von Geheimnissen. + +- **Integration in spezielle Umgebungen** + Ob CLI-Tools, Browser-Apps, Serverless Functions oder Embedded Systems – oft gibt es technische Anforderungen, die einen maßgeschneiderten Client notwendig machen. + +- **Anpassungsfähigkeit bei API-Änderungen und neuen Features** + APIs entwickeln sich weiter. Ein eigener Client hilft, neue oder noch nicht unterstützte Endpunkte zu nutzen oder auf Breaking Changes flexibel zu reagieren. + +- **Architektur- und Integrationsflexibilität** + Wer komplexe Architekturmuster (Mikroservices, Middleware, Plug-ins) nutzt, braucht vielleicht mehr Kontrolle – z.B. für Logging, Tracing, eigenes Rate-Limiting oder um eigene Abstraktionsebenen aufzubauen. + +- **Sicherheit, Compliance und Auditierbarkeit** + Manche Branchen und Organisationen erfordern geprüfte, selbstgehostete Clients, Integration in Security-Tools oder ein individuelles Credential-Management. + +- **Testing, Mocking und lokale Entwicklung** + Eigene Clients können spezielle Features für lokale Entwicklung oder CI bieten – wie Mock-Daten, Test-Doubles oder vereinfachte Authentifizierung in Prototypen. + +- **Dokumentation, Lokalisierung, Onboarding** + Eigenentwickelte Clients lassen sich leicht ans Team oder die Unternehmensprozesse anpassen – bis hin zu lokalisierter Dokumentation oder maßgeschneiderten Einstiegsbeispielen. + +- **Abhängigkeitsmanagement und Code-Ownership** + Du kannst Abhängigkeiten besser kontrollieren und den für dich optimalen API-Umfang gestalten, ohne externe Drift. + +**Zusammengefasst:** +Eigene API-Clients bringen mehr als nur individuelle Präferenzen – sie sind oftmals entscheidend für Integration, Compliance, Sicherheit und die Produktivität im Development. + +Mit einem maßgeschneiderten Client sorgst du dafür, dass deine Anwendungen robust, wartbar und zukunftssicher bleiben. + +## Vorbereitung {#preparation} + +Eine gründliche Vorbereitung ist der wichtigste Schritt für eine effiziente und nachhaltige Entwicklung deines API-Clients. + +Mit den richtigen Voraussetzungen kannst du einen Großteil des Codes automatisch generieren – und sparst viel manuelle Arbeit. Folgende Punkte solltest du vor dem Start klären: + +### Anwendungsfall & Zielumgebung definieren {#use-case-and-goal} + +- **Wo läuft der Client?** + Wird der Client im Server, als Browser-Skript, in einer CLI, als Serverless Function oder im CI/CD genutzt? +- **Wer nutzt ihn?** + Interne Teams, externe User oder Automatisierungstools? Das wirkt sich auf Usability aus. +- **Welche technischen Einschränkungen gibt es?** + Manche Plattformen (z.B. Browser, Lambda) lassen nicht jede Authentifizierung oder Speicherart zu. + +### OpenAPI-Spezifikation prüfen {#get-openapi-specification} + +Lade die aktuelle OpenAPI-Spezifikation der API herunter: + +```shellsession +user@local $ curl --location --fail --silent 'https://api.mittwald.de/v2/openapi.json' > openapi.json +``` + +- **Spezifikation validieren:** + Prüfe sie mit Tools wie [Swagger Editor](https://editor.swagger.io/) auf Fehler oder Inkonsistenzen. +- **Auf Vollständigkeit achten:** + Sind alle relevanten Endpunkte, Authentifizierungen und Schemas dokumentiert? + +### Authentifizierung und Sicherheit klären {#authentication-and-security} + +- **Welche Authentifizierung braucht es?** + API-Tokens, OAuth2, spezielle Erweiterungen? +- **Wie werden die Secrets gemanagt?** + Können sie sicher (z.B. per Env Vars, Configs, Vaults) eingebunden werden? +- **Wie werden die Daten sicher gespeichert?** + Niemals Geheimnisse im Code oder Repository ablegen. + +### Code-Generierungstool auswählen und einrichten {#code-generator} + +- **Welcher Generator?** + Tools wie [OpenAPI Generator](https://openapi-generator.tech/), + [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) oder + [Autorest](https://aka.ms/autorest) unterstützen viele Sprachen. +- **Kompatibilität prüfen:** + Unterstützt das Tool deine Zielsprache und OpenAPI-Version? +- **Tool installieren und konfigurieren:** + Ggf. Generator-Optionen, Vorlagen oder Konfigs anpassen. + +### Generator- & Projektkonfiguration {#code-generator-config} + +- **Generator-Einstellungen prüfen/anpassen:** + Typen, Serialisierung, HTTP-Client, Paketnamen und Code-Style an dein Projekt anpassen. +- **Hilfsdateien bereitstellen:** + Zum Beispiel Umgebungsvariablen, CI-Skripte, Doku oder Tests. +- **Versionierung bedenken:** + Wie wird die API-Version im Client reflektiert (wichtig für Downstream-Kompatibilität)? + +### Umgang mit API-Änderungen & Wartung {#api-evolution-and-maintenance} + +- **Automatische Updates:** + Skripte können Spezifikation holen, Client bauen und Tests laufen lassen. +- **API-Monitoring:** + Changelogs abonnieren, regelmäßige Erneuerung und Tests sicherstellen. +- **Breaking Changes verwalten:** + Versionierung & Update-Strategien planen. + +### Besondere API-Eigenschaften & Custom Logic {#custom-logic} + +- **Gibt es spezielle Endpunkte?** + Pagination, File-Uploads, Webhooks? Generatoren benötigen dafür oft besondere Einstellungen. +- **Fehlerbehandlung:** + Sind die Fehler konsistent? Wie soll der Client damit umgehen? +- **Custom Workflows:** + Müssen bestimmte Businessflows abgebildet werden, kann dies Erweiterungen erfordern. + +Mit solider Vorbereitung sparst du später viel Zeit – und sorgst für einen zuverlässigen, wartbaren und sicheren Client. + +--- + +### OpenAPI-Spezifikation mit Overlays anpassen {#openapi-overlays} + +[OpenAPI Overlays](https://learn.openapis.org/overlay/) sind ein wirkungsvolles und nachhaltiges Mittel, um API-Spezifikationen vor der Codegenerierung gezielt anzupassen. + +Anstatt die ursprüngliche OpenAPI-Spezifikation direkt zu verändern (oder den generierten Client nachträglich zu patchen), kannst du im Overlay gezielt Patch-Operationen definieren – z.B. unerwünschte Endpunkte entfernen oder Dokumentation nachpflegen, ohne den Ursprung zu verändern. + +Wichtige Vorteile: + +- **Reproduzierbare Builds:** Mit Overlays als Code stellst du sicher, dass jeder im Team auf Basis der gleichen, geprüften Anpassungen arbeitet. +- **Trennung von Verantwortlichkeiten:** Die Basis-Spezifikation und deine Anpassungen bleiben klar getrennt und nachvollziehbar. +- **Automatisierungsfähig:** Overlays können in CI/CD-Pipelines genutzt werden, um Clients jederzeit aktuell und angepasst zu generieren. +- **Wartbar:** Du kannst mehrere Overlays stapeln – etwa um Endpunkte zu filtern, Doku zu erweitern oder Beschreibungen zu lokalisieren. + +So gehst du vor: + +1. **Overlay erstellen:** Definiere die Patch-Operationen in einer eigenen Overlay-Datei. +2. **Overlay anwenden:** Tools wie [oas-patcher](https://github.com/mcroissant/oas_patcher) kombinieren Basisspezifikation und Overlay zu einer angepassten OpenAPI-Datei. +3. **Client generieren:** Nutze deinen bevorzugten Generator auf Basis der angepassten Spezifikation. + +:::tip +🌱 **Best Practice:** Investiere Zeit und Qualität in deine Build- und Overlay-Prozesse – nicht in das Nachbearbeiten von generiertem Code. Das reduziert technischen Ballast und sorgt für schnelle, fehlerfreie Prototypen und Releases. +::: + +**Contract-Check:** +Teste stets, ob jedes `operationId` deiner (eventuell gefilterten) Spezifikation auch tatsächlich als aufrufbare Methode im generierten Client landet. So verhinderst du, dass durch Overlays wichtige Endpunkte oder Integrationen aus Versehen verloren gehen. + +**Typischer Fehler:** +Patching am generierten Client ist fehleranfällig und wartungsintensiv. Bevorzuge stets die Steuerung über Overlays und Generator-Konfiguration. + +--- + +### Nächste Schritte {#next-steps} + +- Sieh dir die sprachspezifischen Anleitungen für konkrete End-to-End-Beispiele an (z.B. [Python SDK Generierung](/docs/v2/api/sdks/python)). +- Integriere Overlays und Automatisierung in deine CI/CD-Pipeline, um Clients immer aktuell zu halten. +- Für fortgeschrittene Szenarien – z.B. mehrere Sprachen oder tiefgreifende Custom-Workflows – erweitere deine Overlays und Codegeneration nach Bedarf.