Die beste API nützt nichts, wenn niemand versteht, wie man sie benutzt. Gute Dokumentation ist der Unterschied zwischen: Ich habe das in 5 Minuten integriert – und – Ich habe 2 Tage damit verschwendet.
Developer Experience (DX) geht über Dokumentation hinaus: Beispiele, die funktionieren. Fehlermeldungen, die helfen. SDKs, die Arbeit abnehmen. Dieser Artikel zeigt, wie du deine API für Entwickler zugänglich machst.
Zielbild
Nach diesem Artikel kannst du:
- OpenAPI-Spezifikationen schreiben und validieren
- Beispiele erstellen, die wirklich funktionieren
- Authentication-Guides für verschiedene Flows schreiben
- Entscheiden, ob SDKs sinnvoll sind
- API Explorer und Sandboxes einsetzen
- Onboarding für neue Entwickler optimieren
Kernfragen
Bevor du weiterliest, versuche diese Fragen für dein Projekt zu beantworten:
- Welches Format? OpenAPI 3.x? AsyncAPI? Etwas anderes?
- Welche Beispiele braucht ihr? Jeden Endpoint? Nur die wichtigsten?
- Braucht ihr SDKs? Für welche Sprachen?
- Wie testen Entwickler? Sandbox? Postman? curl?
- Wie erreichen euch Entwickler bei Problemen? Support? Community?
OpenAPI Specification
OpenAPI (früher Swagger) ist der Standard für API-Dokumentation.
Warum OpenAPI?
| Vorteil | Beschreibung |
|---|---|
| Maschinenlesbar | Tools können Docs, SDKs, Tests generieren |
| Standardisiert | Entwickler kennen das Format |
| Validierbar | CI kann Spec gegen Code prüfen |
| Interaktiv | Swagger UI, Redoc, etc. |
Grundstruktur
openapi: 3.1.0
info:
title: Example API
version: 2.3.1
description: |
Die Example API ermöglicht...
## Authentifizierung
Alle Requests benötigen einen Bearer Token...
servers:
- url: https://api.example.com/v2
description: Production
- url: https://api.staging.example.com/v2
description: Staging
security:
- bearerAuth: [ ]
paths:
/orders:
get:
summary: List orders
operationId: listOrders
# ...
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
Endpoint-Dokumentation
paths:
/orders:
get:
summary: List orders
description: |
Gibt eine paginierte Liste aller Orders zurück.
Unterstützt Filtering nach Status und Datum.
operationId: listOrders
tags:
- Orders
parameters:
- name: status
in: query
description: Filter by order status
schema:
type: string
enum: [ pending, confirmed, shipped, delivered ]
example: pending
- name: limit
in: query
description: Maximum number of results
schema:
type: integer
minimum: 1
maximum: 100
default: 20
example: 50
- name: cursor
in: query
description: Pagination cursor from previous response
schema:
type: string
example: eyJpZCI6MTIzfQ
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/OrderList'
example:
data:
- id: order_abc123
status: pending
total: 9999
created_at: '2026-01-19T10:30:00Z'
pagination:
next_cursor: eyJpZCI6NDU2fQ
has_more: true
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
Schema-Definitionen
components:
schemas:
Order:
type: object
required:
- id
- status
- total
- created_at
properties:
id:
type: string
description: Unique order identifier
example: order_abc123
pattern: '^order_[a-z0-9]+$'
status:
type: string
enum: [ pending, confirmed, shipped, delivered, cancelled ]
description: Current order status
example: pending
total:
type: integer
format: int64
description: Total amount in cents
example: 9999
minimum: 0
currency:
type: string
description: ISO 4217 currency code
example: EUR
default: EUR
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
created_at:
type: string
format: date-time
description: Creation timestamp (ISO 8601)
example: '2026-01-19T10:30:00Z'
metadata:
type: object
additionalProperties: true
description: Custom key-value pairs
example:
customer_note: "Please gift wrap"
Error Responses
components:
responses:
BadRequest:
description: Invalid request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Error'
example:
type: https://api.example.com/errors/validation-failed
title: Validation Failed
status: 400
error_code: VALIDATION_FAILED
detail: The request body contains invalid fields.
request_id: req_abc123
errors:
- field: email
code: INVALID_FORMAT
message: Must be a valid email address.
schemas:
Error:
type: object
required:
- type
- title
- status
- error_code
properties:
type:
type: string
format: uri
title:
type: string
status:
type: integer
error_code:
type: string
detail:
type: string
request_id:
type: string
errors:
type: array
items:
$ref: '#/components/schemas/FieldError'
OpenAPI Validierung in CI
# .github/workflows/api.yml
name: API Validation
on: [ push, pull_request ]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Validate OpenAPI
uses: char0n/swagger-editor-validate@v1
with:
definition-file: openapi.yaml
- name: Check for breaking changes
run: |
git show origin/main:openapi.yaml > /tmp/openapi-main.yaml
npx oasdiff breaking /tmp/openapi-main.yaml openapi.yaml
Beispiele, die funktionieren
Beispiele sind das Wichtigste in der Dokumentation. Sie müssen funktionieren.
Anforderungen an Beispiele
| Anforderung | Warum? |
|---|---|
| Vollständig | Copy-Paste muss funktionieren |
| Realistisch | Keine foo, bar, test123 |
| Konsistent | Gleiche IDs/Daten überall |
| Aktuell | Bei API-Änderungen updaten |
Request-Beispiele
Beispiel: Order anlegen.
Request:
curl -X POST https://api.example.com/v2/orders \
-H "Authorization: Bearer sk_live_abc123" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ord_req_xyz789" \
-d '{
"customer_id": "cus_def456",
"items": [
{
"product_id": "prod_ghi789",
"quantity": 2
}
],
"shipping_address": {
"line1": "123 Main St",
"city": "Berlin",
"postal_code": "10115",
"country": "DE"
}
}'
Response:
{
"id": "order_abc123",
"status": "pending",
"customer_id": "cus_def456",
"items": [
{
"product_id": "prod_ghi789",
"name": "Widget Pro",
"quantity": 2,
"unit_price": 4999,
"total": 9998
}
],
"subtotal": 9998,
"shipping": 499,
"total": 10497,
"currency": "EUR",
"created_at": "2026-01-19T10:30:00Z"
}
Error-Beispiele
Zeige auch, was schiefgehen kann. Beispiel:
Validation Error (400)
curl -X POST https://api.example.com/v2/orders \
-H "Authorization: Bearer sk_live_abc123" \
-H "Content-Type: application/json" \
-d '{"customer_id": ""}'
{
"type": "https://api.example.com/errors/validation-failed",
"title": "Validation Failed",
"status": 400,
"error_code": "VALIDATION_FAILED",
"request_id": "req_xyz789",
"errors": [
{
"field": "customer_id",
"code": "REQUIRED",
"message": "Customer ID is required."
},
{
"field": "items",
"code": "REQUIRED",
"message": "At least one item is required."
}
]
}
Rate Limit (429)
{
"type": "https://api.example.com/errors/rate-limit-exceeded",
"title": "Too Many Requests",
"status": 429,
"error_code": "RATE_LIMIT_EXCEEDED",
"detail": "Rate limit exceeded. Please wait 30 seconds.",
"request_id": "req_abc123"
}
Response Headers:
Retry-After: 30
RateLimit-Policy: "user";q=100;w=60
RateLimit: "user";r=0;t=30
Beispiele testen
Beispiele automatisch testen:
# tests/test_docs_examples.py
import subprocess
import json
def test_create_order_example():
"""Test that the documented curl example works."""
result = subprocess.run([
"curl", "-s", "-X", "POST",
"https://api.staging.example.com/v2/orders",
"-H", f"Authorization: Bearer {TEST_API_KEY}",
"-H", "Content-Type: application/json",
"-d", json.dumps({
"customer_id": "cus_test",
"items": [{"product_id": "prod_test", "quantity": 1}]
})
], capture_output=True, text=True)
response = json.loads(result.stdout)
assert "id" in response
assert response["status"] == "pending"
Authentication Guide
Auth ist oft der schwierigste Teil. Dokumentiere ihn gut.
Übersicht
Die Example API unterstützt zwei Authentifizierungsmethoden:
| Methode | Use Case | Empfohlen für |
|---|---|---|
| API Keys | Server-to-Server | Backend-Integration |
| OAuth 2.0 | User-Kontext | Mobile/Web Apps |
API Keys
API Key erstellen
- Gehe zu dashboard.example.com/api-keys
- Klicke
Create API Key - Wähle die benötigten Scopes
- Kopiere den Key (wird nur einmal angezeigt)
API Key verwenden
curl https://api.example.com/v2/orders \
-H "Authorization: Bearer sk_live_abc123"
Environments
| Environment | Key-Präfix | URL |
|---|---|---|
| Production | sk_live_ |
api.example.com |
| Test | sk_test_ |
api.staging.example.com |
Wichtig: Test-Keys funktionieren nur gegen die Staging-API. Production-Keys niemals in Client-Code oder Repos committen.
OAuth 2.0
Flows
| Flow | Use Case |
|---|---|
| Authorization Code + PKCE | Web/Mobile mit User-Login |
| Client Credentials | Server-to-Server |
Authorization Code Flow
- User zu Authorization URL leiten:
https://auth.example.com/oauth/authorize?
client_id=YOUR_CLIENT_ID&
redirect_uri=https://yourapp.com/callback&
response_type=code&
scope=orders:read orders:write&
state=random_state_string&
code_challenge=BASE64_CHALLENGE&
code_challenge_method=S256
- Authorization Code gegen Token tauschen:
curl -X POST https://auth.example.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=https://yourapp.com/callback" \
-d "client_id=YOUR_CLIENT_ID" \
-d "code_verifier=ORIGINAL_VERIFIER"
- Access Token verwenden:
curl https://api.example.com/v2/orders \
-H "Authorization: Bearer ACCESS_TOKEN"
Token Refresh
curl -X POST https://auth.example.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=REFRESH_TOKEN" \
-d "client_id=YOUR_CLIENT_ID"
SDKs und Client Libraries
SDKs können Integration drastisch vereinfachen.
Wann SDKs?
| Pro SDK | Contra SDK |
|---|---|
| Komplexe Auth (OAuth) | Einfache REST-API |
| Viele Sprachen im Einsatz | Wenige Integratoren |
| Komplexe Datentypen | Maintenance-Aufwand |
| Retry-Logic eingebaut | SDK-Bugs = Support-Tickets |
SDK-Generierung
Aus OpenAPI automatisch generieren:
# OpenAPI Generator
openapi-generator generate \
-i openapi.yaml \
-g typescript-fetch \
-o ./sdk/typescript
# Speakeasy (kommerzielle Alternative)
speakeasy generate sdk \
--schema openapi.yaml \
--lang typescript \
--out ./sdk/typescript
SDK-Beispiel
TypeScript SDK
Installation:
npm install @example/api-sdk
Quickstart:
import {ExampleAPI} from '@example/api-sdk';
const api = new ExampleAPI({
apiKey: 'sk_live_abc123'
});
// List orders
const orders = await api.orders.list({
status: 'pending',
limit: 50
});
// Create order
const order = await api.orders.create({
customer_id: 'cus_def456',
items: [
{product_id: 'prod_ghi789', quantity: 2}
]
});
console.log(order.id); // order_abc123
Error Handling:
import {ExampleAPI, ValidationError, RateLimitError} from '@example/api-sdk';
try {
await api.orders.create({ /* ... */});
} catch (error) {
if (error instanceof ValidationError) {
console.log(error.errors); // Field-level errors
} else if (error instanceof RateLimitError) {
console.log(`Retry after ${error.retryAfter} seconds`);
}
}
API Explorer und Sandbox
Interaktives Testen macht das Lernen einfacher.
Swagger UI / Redoc
# Einbetten in Docs
x-logo:
url: https://example.com/logo.png
altText: Example API
x-tagGroups:
- name: Orders
tags:
- Orders
- Order Items
- name: Customers
tags:
- Customers
Sandbox-Umgebung
| Feature | Production | Sandbox |
|---|---|---|
| URL | api.example.com | sandbox.api.example.com |
| API Key | sk_live_* |
sk_test_* |
| Daten | Echte Daten | Test-Daten |
| Limits | Voll | Reduziert |
| Webhooks | Echte Events | Simulierte Events |
Test-Daten
Dokumentiere vordefinierte Test-Daten, damit Integrationen reproduzierbar sind.
Test Customers:
| ID | Name | Beschreibung |
|---|---|---|
cus_test_success |
Test Success | Alle Operationen erfolgreich |
cus_test_decline |
Test Decline | Zahlungen werden abgelehnt |
cus_test_error |
Test Error | Simuliert Server-Fehler |
Test Products:
| ID | Name | Preis |
|---|---|---|
prod_test_widget |
Test Widget | €49.99 |
prod_test_gadget |
Test Gadget | €99.99 |
Fehler simulieren:
Um einen 429 Rate Limit Error zu simulieren:
curl https://sandbox.api.example.com/v2/orders \
-H "Authorization: Bearer sk_test_abc123" \
-H "X-Simulate-Error: rate_limit"
Onboarding
Der erste Eindruck zählt. Mach den Einstieg einfach.
Quickstart Guide
Ein Quickstart sollte in unter 5 Minuten zur ersten erfolgreichen Response führen.
1. API Key erstellen
Registriere dich und erstelle einen Test-API-Key (dashboard.example.com).
2. Ersten Request machen
curl https://api.example.com/v2/orders \
-H "Authorization: Bearer YOUR_API_KEY"
3. Order erstellen
curl -X POST https://api.example.com/v2/orders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cus_test_success",
"items": [{"product_id": "prod_test_widget", "quantity": 1}]
}'
Nächste Schritte
Glossar
Erkläre Domain-spezifische Begriffe, damit neue Teams schneller onboarden.
| Begriff | Definition |
|---|---|
| Order | Eine Bestellung eines Kunden |
| Line Item | Ein einzelner Posten in einer Order |
| Fulfillment | Der Prozess der Auftragsabwicklung |
| Idempotency Key | Eindeutiger Schlüssel zur Vermeidung doppelter Requests |
| Webhook | HTTP-Callback bei Events |
| Cursor | Opaker String für Pagination |
Support und Feedback
Entwickler brauchen Hilfe. Mach es ihnen einfach.
Support-Kanäle
| Kanal | Use Case | Response Time |
|---|---|---|
| Docs | Self-Service | Sofort |
| FAQ | Häufige Fragen | Sofort |
| GitHub Issues | Bugs, Feature Requests | 1-3 Tage |
| Discord/Slack | Community-Support | Variabel |
| Kritische Issues | 24h | |
| Enterprise Support | SLA-gebunden | 1-4h |
Feedback sammeln
Ein kurzes Feedback-Widget reicht:
- Frage: War diese Seite hilfreich?
- Schnellfeedback: 👍 Ja / 👎 Nein
- Optionales Freitextfeld + Absenden
Status Page
Verlinke eine Status Page sichtbar und beschreibe, was dort zu finden ist:
- Aktuelle Verfügbarkeit und Incidents
- status.example.com
- Abo-Optionen: RSS, E-Mail, Slack
Regeln & Anti-Patterns
Do
- OpenAPI als Single Source of Truth
- Beispiele, die Copy-Paste funktionieren
- Error-Beispiele für jeden Fehlertyp
- Auth-Guide mit Schritt-für-Schritt-Anleitung
- Sandbox für risikofreies Testen
- Quickstart-Guide für schnellen Einstieg
- Glossar für Domain-Begriffe
- Changelog und Versionshinweise
- Feedback-Möglichkeit auf jeder Seite
Don't
- Veraltete Beispiele
foo,bar,testals Beispielwerte- Auth ohne Code-Beispiele
- Nur generierte Docs ohne Kontext
- Broken Links
- Docs ohne Suche
- Keine Error-Dokumentation
- SDK ohne Beispiele
Artefakt: Dokumentations-Checkliste
# API-Dokumentations-Checkliste
## OpenAPI Spec
- [ ] OpenAPI 3.x Format
- [ ] Alle Endpoints dokumentiert
- [ ] Request/Response Schemas definiert
- [ ] Beispiele für jeden Endpoint
- [ ] Error Responses dokumentiert
- [ ] Authentication dokumentiert
- [ ] CI-Validierung eingerichtet
## Beispiele
### Für jeden Endpoint
- [ ] curl-Beispiel (Request)
- [ ] Response-Beispiel (Success)
- [ ] Error-Beispiel (mindestens 400, 401)
### Qualität
- [ ] Realistische Daten (keine `foo`, `bar`)
- [ ] Konsistente IDs über Beispiele hinweg
- [ ] Vollständig (Copy-Paste funktioniert)
- [ ] Automatisch getestet
## Authentication
- [ ] Übersicht der Auth-Methoden
- [ ] API Key: Erstellen, Verwenden, Scopes
- [ ] OAuth: Flows, Endpoints, Beispiele
- [ ] Token Refresh dokumentiert
- [ ] Fehler bei Auth dokumentiert
## Getting Started
- [ ] Quickstart-Guide (< 5 Minuten)
- [ ] Schritt-für-Schritt mit Code
- [ ] Link zu API Key erstellen
- [ ] Erster Request zum Testen
## Reference
- [ ] Alle Endpoints
- [ ] Alle Parameter
- [ ] Alle Schemas
- [ ] Alle Error Codes
- [ ] Rate Limits
- [ ] Pagination erklärt
## SDKs (falls vorhanden)
- [ ] Installation
- [ ] Quickstart
- [ ] Error Handling
- [ ] Alle Sprachen dokumentiert
## Sandbox / Testing
- [ ] Sandbox-URL dokumentiert
- [ ] Test-API-Keys erklärt
- [ ] Test-Daten dokumentiert
- [ ] Error-Simulation erklärt
## Support
- [ ] Support-Kanäle dokumentiert
- [ ] FAQ vorhanden
- [ ] Status Page verlinkt
- [ ] Feedback-Möglichkeit
## Meta
- [ ] Glossar / Begriffserklärungen
- [ ] Changelog
- [ ] Versionierung erklärt
- [ ] Suchfunktion
- [ ] Mobile-freundlich
Checkliste
Bevor du zum nächsten Artikel gehst, prüfe:
- [ ] OpenAPI-Spec ist vollständig und validiert
- [ ] Beispiele funktionieren (getestet!)
- [ ] Auth-Guide mit Code-Beispielen
- [ ] Quickstart-Guide existiert
- [ ] Error Responses sind dokumentiert
- [ ] Sandbox/Test-Umgebung ist dokumentiert
- [ ] Support-Kanäle sind klar
- [ ] Glossar für Domain-Begriffe
- [ ] Dokumentations-Checkliste ist abgearbeitet
Wie es weitergeht
Im nächsten Teil geht es um Testing und Quality Gates: Wie du sicherstellst, dass deine API funktioniert, bevor sie live geht – von Unit Tests über Contract Tests bis zu Security Scans.
Alle Teile der Serie: Serie: API-Design