REST API Design für Großsysteme
REST APIs sind langfristige Verträge. Entscheidend sind Stabilität, Fehlerverträge, Versionierung und Konsistenz.
RESTOpenAPIProblem DetailsVersionierung
API als Vertrag
Eine interne API kann genauso kritisch sein wie eine öffentliche API. Breaking Changes erzeugen Abhängigkeitsschäden in anderen Teams.
Ressourcen
| Gut | Schlecht |
|---|---|
| POST /orders | POST /createOrder |
| GET /orders/{id} | GET /getOrderById |
| POST /orders/{id}/cancellation | POST /cancel |
| GET /orders?customerId=... | POST /searchOrders ohne Not |
Fehler
Problem-Details-ähnlicher Fehlervertrag
{
"type": "https://errors.example.com/order/invalid-state",
"title": "Order cannot be cancelled",
"status": 409,
"detail": "Order ORD-4711 is already invoiced.",
"traceId": "4e7f9a2c8d",
"code": "ORDER_ALREADY_INVOICED"
}
Versionierung
Versionierung ist kein Ersatz für Kompatibilität. Neue optionale Felder sind meist besser als harte Brüche. Entfernen ist gefährlicher als Ergänzen.
Beispiel
DTO übersetzt in Command
public record PlaceOrderRequest(
String customerId,
List<OrderLineRequest> lines,
String idempotencyKey) {
PlaceOrderCommand toCommand() {
return new PlaceOrderCommand(new CustomerId(customerId),
lines.stream().map(OrderLineRequest::toDomain).toList(),
idempotencyKey);
}
}
Checkliste
- Ist jeder Fehler maschinenlesbar?
- Gibt es eine TraceId?
- Ist Idempotenz für POST geklärt?
- Ist die OpenAPI-Beschreibung Teil des Builds?
- Gibt es Contract Tests?