#Fehler und Grenzen
#Das Format
Jede Fehlerantwort der API v1 ist ein Problem nach RFC 9457 („Problem Details for HTTP APIs“) mit dem Medientyp application/problem+json (Beispiel):
| Feld | Inhalt |
|---|---|
type | URI des Problemtyps — ein Typ je Code, sie führt zu seiner Zeile in der Tabelle unten, etwa https://docs.logicar.cloud/api/fehler#invalid-request. |
title | Kurzer Titel des Typs, für jedes Auftreten gleich. |
status | Der HTTP-Status dieser Antwort. |
detail | Was in diesem Fall nicht stimmt, ein Satz für Menschen (englisch). Er kann sich ändern. |
instance | Der Pfad Ihrer Anfrage. |
code | Der feste Code zum Auswerten, etwa INVALID_REQUEST. |
requestId | Die Kennung des Aufrufs, auch im Kopf X-Request-Id. Nennen Sie sie uns bei Rückfragen. |
errors | Nur bei Feldfehlern (400 INVALID_REQUEST, 422): jedes beanstandete Feld. |
Werten Sie code aus (oder gleichwertig type), nicht detail — der Satz kann sich ändern, der Code nicht. Manche Codes geben zusätzliche Felder mit, etwa required und granted bei INSUFFICIENT_SCOPE; die Tabelle nennt sie. Felder, die Ihr System nicht kennt, übergeht es bitte. Interne Einzelheiten wie ein Stacktrace oder Kennungen anderer Konten stehen in keiner Antwort; bei 500 hilft uns die requestId.
#Fehlercodes
| HTTP | Code | Bedeutung | Was tun |
|---|---|---|---|
| 400 | INVALID_REQUEST | Ein Pflichtfeld fehlt, ein Wert ist falsch oder ein Feld unbekannt. errors nennt jedes Feld mit Code und Grund — alle auf einmal; im Rumpf mit pointer (JSON Pointer), in Pfad und Abfrage mit parameter. | Anfrage korrigieren. Unverändert wiederholt, bleibt es ein Fehler. |
| 400 | INVALID_JSON | Der Rumpf ist kein gültiges JSON. | Gültiges JSON mit Content-Type: application/json senden. |
| 400 | INVALID_IDEMPOTENCY_KEY | Idempotency-Key ist länger als 200 Zeichen. | Einen kürzeren Schlüssel verwenden, etwa eine UUID. |
| 400 | INVALID_CURSOR | Der cursor der Liste ist ungültig. | Den nextCursor der letzten Seite unverändert zurückgeben. |
| 400 | INVALID_WEBHOOK_URL | Die Webhook-Adresse ist nicht erlaubt; reason nennt den Grund, etwa HTTPS_REQUIRED oder PRIVATE_ADDRESS. | Eine öffentliche https-Adresse ohne Weiterleitung eintragen. |
| 400 | INVALID_SCENARIO | Nur Sandbox: unbekannter Wert in X-Sandbox-Scenario — bei POST /quotes jeder außer QUOTE_REQUIRED. allowed nennt die möglichen. | Einen Wert aus der Tabelle der Szenarien verwenden; bei POST /quotes den Kopf weglassen. |
| 401 | UNAUTHORIZED | Die Anfrage trägt keine Anmeldung. | Authorization: Bearer <Token oder Schlüssel> oder X-API-Key mitschicken. |
| 401 | INVALID_CREDENTIALS | Der Schlüssel ist unbekannt oder widerrufen — oder der Zugang hinter einem Token gibt es nicht mehr. | Den Zugang im Portal prüfen; ein widerrufener kommt nicht zurück. |
| 401 | TOKEN_EXPIRED | Das Zugriffstoken ist abgelaufen (nach einer Stunde). | Ein neues Token holen (POST /oauth/token) und den Aufruf wiederholen. |
| 401 | INVALID_TOKEN | Das Zugriffstoken ist ungültig — verändert, gekürzt oder nicht von LOGICAR. | Ein neues Token holen und es unverändert mitschicken. |
| 401 | ACCESS_TOKEN_REQUIRED | Das Secret eines OAuth-Clients wurde als Schlüssel geschickt. Ein OAuth-Client holt erst ein Token. | Mit Client-Kennung und Secret POST /oauth/token aufrufen und das Token mitschicken. |
| 401 | CREDENTIALS_EXPIRED | Der Zugang ist abgelaufen (Ablaufdatum im Portal). | Im Portal einen neuen Zugang anlegen oder die Laufzeit verlängern lassen. |
| 401 | CREDENTIALS_DISABLED | Der Zugang ist gesperrt. | Im Portal wieder freigeben — oder den Grund der Sperre klären. |
| 403 | ACCOUNT_SUSPENDED | Ihr Konto ist gesperrt. | Uns kontaktieren. |
| 403 | ACCOUNT_NOT_ELIGIBLE | Das Konto ist kein Auftraggeber-Konto. | Uns kontaktieren — Schnittstellen sind für Auftraggeber. |
| 403 | FEATURE_NOT_ENABLED | Die API v1 ist für den Echtbetrieb Ihres Kontos noch nicht freigeschaltet. Die Sandbox ist es immer. | Die Freischaltung bei Ihrem Ansprechpartner anfragen. |
| 403 | QUOTE_ACCEPTANCE_NOT_AGREED | Ihre Vereinbarung sieht die Annahme von Angeboten über die Schnittstelle nicht vor. | Das Angebot über den Link in der Angebotsmail annehmen — oder die Annahme per API in die Vereinbarung aufnehmen lassen. |
| 403 | SANDBOX_ONLY | Diesen Endpunkt gibt es nur in der Sandbox. | Mit einem Testschlüssel (lc_test_…) oder einem Sandbox-Token aufrufen. |
| 403 | INSUFFICIENT_SCOPE | Dem Zugang fehlt das Recht für diesen Aufruf. required nennt es, granted die vorhandenen. | Im Portal dem Zugang das Recht geben — und ein neues Token holen, wenn es auf das Recht beschränkt war. |
| 403 | IP_BLOCKED | Anfragen von Ihrer Absenderadresse sind bei LOGICAR gesperrt. | Uns kontaktieren, mit der requestId der Antwort. |
| 404 | NOT_FOUND | Diesen Endpunkt gibt es nicht. | Pfad und Methode prüfen. |
| 404 | ORDER_NOT_FOUND | Zu dieser Kennung gibt es in Ihrem Konto keinen Auftrag und keine Anfrage. | Kennung prüfen. Sandbox und Echtbetrieb sind getrennt. |
| 404 | DOCUMENT_NOT_FOUND | Dieses Dokument gibt es am Auftrag nicht — oder es ist für diesen Zugang nicht sichtbar. | Die Liste GET …/documents abfragen; Rechte des Zugangs prüfen. |
| 404 | QUOTE_NOT_FOUND | Zu dieser Kennung gibt es in Ihrem Konto keine Anfrage und kein Angebot. | Kennung der Anfrage, Anfrage- oder Angebotsnummer prüfen. Sandbox und Echtbetrieb sind getrennt. |
| 404 | QUOTE_DOCUMENT_NOT_FOUND | Zu diesem Angebot gibt es (noch) kein PDF — in der Sandbox nie. | Warten, bis das Angebot vorliegt (OFFERED); in der Sandbox gibt es keine Dokumente. |
| 404 | SUBSCRIPTION_NOT_FOUND | Diesen Webhook-Endpunkt gibt es in der Umgebung des Zugangs nicht. | Kennung und Umgebung (Test- oder Live-Schlüssel) prüfen. |
| 409 | IDEMPOTENCY_KEY_REUSED | Derselbe Idempotency-Key — oder dieselbe externalOrderId — kam mit anderem Inhalt. Hat der Schlüssel schon vor mehr als 24 Stunden einen Auftrag angelegt, nennt existing diesen Auftrag (kind, id, Nummer). | Für einen neuen Auftrag einen neuen Schlüssel verwenden; denselben nur für Wiederholungen. |
| 409 | IDEMPOTENCY_REQUEST_IN_PROGRESS | Der erste Aufruf mit diesem Schlüssel läuft noch. | Nach Retry-After Sekunden wiederholen. |
| 409 | EXTERNAL_ORDER_ID_EXISTS | Unter dieser externalOrderId liegt schon ein Auftrag oder eine Anfrage. existing nennt ihn: kind, id und die Nummer. | Den vorhandenen Vorgang abfragen, statt einen zweiten anzulegen. |
| 409 | NO_CONTRACTING_PARTY | Für Ihr Konto ist kein Auftraggeber (kaufmännischer Ansprechpartner) hinterlegt. | Uns kontaktieren — das ist eine Lücke in der Einrichtung. |
| 409 | ORDER_NOT_CHANGEABLE | Ab der Abholung ändert die API nichts mehr; eine Anfrage, die auf ein Angebot wartet, gar nicht. | Uns anrufen — oder die Anfrage zurückziehen und neu stellen. |
| 409 | ORDER_NOT_CANCELLABLE | Ab der Abholung storniert die API nicht mehr; eine abgeschlossene Anfrage lässt sich nicht zurückziehen. | Uns anrufen: dann ist ein Fahrer mit dem Fahrzeug unterwegs. |
| 409 | REQUEST_HAS_QUOTE | Zu dieser Anfrage liegt schon ein Angebot vor. | Das Angebot ablehnen (POST /quotes/{id}/decline), statt die Anfrage zurückzuziehen. |
| 409 | QUOTE_NOT_OFFERED | Zu dieser Anfrage liegt (noch) kein Angebot vor, das sich annehmen oder ablehnen ließe. | Den Stand mit GET /quotes/{id} abfragen; vor dem Angebot die Anfrage bei Bedarf zurückziehen (POST /orders/{id}/cancel). |
| 409 | QUOTE_VERSION_MISMATCH | Angeboten ist eine andere Fassung als die genannte (nachverhandelt). currentVersion nennt die aktuelle. | Die aktuelle Fassung lesen und, wenn sie passt, diese annehmen. |
| 409 | QUOTE_EXPIRED | Die Gültigkeit des Angebots ist abgelaufen. | Ein neues Angebot anfordern (POST /quotes). |
| 409 | QUOTE_ALREADY_DECIDED | Über das Angebot ist schon entschieden — angenommen, abgelehnt oder zurückgezogen. quoteStatus nennt den Stand. | Den Stand mit GET /quotes/{id} abfragen; nach einer Annahme steht der Auftrag in order. |
| 409 | SANDBOX_FINISHED | Nur Sandbox: das Szenario dieses Vorgangs ist durchgelaufen. | Einen neuen Testvorgang anlegen. |
| 409 | TOO_MANY_SUBSCRIPTIONS | Höchstens zehn Webhook-Endpunkte je Umgebung. | Einen nicht mehr gebrauchten Endpunkt löschen. |
| 413 | PAYLOAD_TOO_LARGE | Der Rumpf ist zu groß. | Freie Daten kürzen (metadata, instructions). |
| 415 | UNSUPPORTED_MEDIA_TYPE | Zeichensatz oder Kodierung des Rumpfs kennen wir nicht — etwa charset=iso-8859-1 oder Content-Encoding: br. | JSON in UTF-8 senden — unkomprimiert oder mit gzip bzw. deflate. |
| 422 | VEHICLE_NOT_DRIVEABLE | DRIVEN, aber das Fahrzeug ist nicht fahrbereit oder nicht verkehrssicher. | TRAILER oder TRUCK wählen — oder die Angabe zum Fahrzeug prüfen. |
| 422 | SERVICE_NOT_SUPPORTED | Eine Leistung, die LOGICAR nicht anbietet (Ausfuhrkennzeichen, Zoll). | Die Leistung weglassen und selbst beauftragen. |
| 422 | SERVICE_NOT_APPLICABLE | Die Leistung passt nicht zum Auftrag, etwa ein Kurzzeitkennzeichen für einen Transport auf dem Lkw. Ein Kurzzeitkennzeichen gibt es außerdem nur für Privatkunden (ein selbst registriertes Konto ohne Firmennamen) und nur mit requestedPickup mindestens 7 Tage im Voraus — das gilt auch bei der Annahme eines Angebots (POST /quotes/{id}/accept). service und reason nennen Leistung und Grund. | Die Leistung weglassen — bei einem Angebot eine neue Fassung bei LOGICAR anfordern. |
| 422 | TRANSPORT_TYPE_NOT_ALLOWED | Ihre Vereinbarung lässt diese Transportart nicht zu. | Eine vereinbarte Transportart wählen oder die Vereinbarung erweitern lassen. |
| 429 | RATE_LIMITED | Zu viele Anfragen mit diesem Zugang — oder zu viele abgewiesene Anmeldungen von Ihrer Adresse. limit und windowSeconds nennen die Grenze. | Nach Retry-After Sekunden wiederholen. |
| 429 | SANDBOX_LIMIT | Nur Sandbox: das Tageslimit an Testvorgängen ist erreicht. | Am nächsten Tag weiter testen oder uns um ein höheres Limit bitten. |
| 500 | INTERNAL_ERROR | Unerwarteter Fehler auf unserer Seite — oder ein Dokument, dessen Prüfsumme nicht stimmt. | Später wiederholen, mit demselben Idempotency-Key. Die requestId hilft uns beim Suchen. |
| 503 | MAINTENANCE | LOGICAR wird gewartet. maintenanceMessage und estimatedResumption nennen Anlass und erwartetes Ende, wenn bekannt. | Später wiederholen — steht Retry-After im Kopf, nach so vielen Sekunden. |
| 503 | NUMBER_COLLISION | Nur Sandbox: bei der Vergabe der Nummer kam ein gleichzeitiger Aufruf dazwischen. | Unverändert erneut senden. |
Die bisherige Schnittstelle hat ihr eigenes Format und ihre eigenen Codes.
#Eingabefehler im Einzelnen
Bei INVALID_REQUEST nennt errors jedes beanstandete Feld — alle auf einmal, nicht nur das erste. Felder im Rumpf stehen als JSON Pointer (RFC 6901) in pointer, geschrieben wie im Beispiel von RFC 9457 mit führendem #; Parameter in Pfad oder Abfrage stehen mit ihrem Namen in parameter. code ist die Art des Fehlers:
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json; charset=utf-8
X-Request-Id: 0e6a5b8c-3f1d-4d2a-9c7e-5b4a3f2e1d0c{
"type": "https://docs.logicar.cloud/api/fehler#invalid-request",
"title": "The request is not valid",
"status": 400,
"detail": "The request is invalid. See errors.",
"instance": "/api/v1/extern/orders",
"code": "INVALID_REQUEST",
"requestId": "0e6a5b8c-3f1d-4d2a-9c7e-5b4a3f2e1d0c",
"errors": [
{ "pointer": "#/pickup/postalCode", "code": "invalid_type", "detail": "Invalid input: expected string, received undefined" },
{ "pointer": "#/vehicle/vin", "code": "invalid_format", "detail": "A VIN has 17 characters: letters and digits, no I, O or Q." },
{ "pointer": "#/pickup/zip", "code": "unrecognized_key", "detail": "Unknown field." }
]
}Häufige Werte von code: invalid_type (fehlt oder falscher Typ), invalid_value (Wert nicht erlaubt), invalid_format (etwa FIN oder Zeitpunkt), too_big / too_small (Länge oder Zahl außerhalb der Grenzen), unrecognized_key (Feld gibt es nicht — etwa ein Tippfehler oder ein Preisfeld). Ein Eintrag der Liste GET /orders?limit=500 sähe so aus: { "parameter": "limit", "code": "too_big", "detail": "…" }.
Fachliche Absagen (422) haben dieselbe Form: code und detail des Problems sind die des ersten Grundes, errors nennt jeden Grund mit seinem eigenen Code und dem Feld (Beispiel).
#Token-Endpunkt
POST /oauth/token antwortet nach OAuth 2.0 (RFC 6749) mit error und error_description als application/json — so lesen es OAuth-Bibliotheken. Daneben stehen dieselben Felder wie in jedem Problem; code ist dort der Code von OAuth. Mehr unter Anmeldung.
| HTTP | error | Bedeutung |
|---|---|---|
| 400 | invalid_request | grant_type fehlt, oder die Anmeldung steht zugleich im Kopf (Basic) und im Rumpf. |
| 400 | unsupported_grant_type | Nur client_credentials ist möglich. |
| 401 | invalid_client | Client-Kennung oder Secret falsch — oder der Zugang ist widerrufen, abgelaufen oder gesperrt. Welche Hälfte nicht stimmte, sagen wir absichtlich nicht. |
| 400 | unauthorized_client | Das Konto ist gesperrt, kein Auftraggeber-Konto oder für den Echtbetrieb der API v1 nicht freigeschaltet. |
| 400 | invalid_scope | Ein angefragtes Recht hat der Zugang nicht — oder er hat gar keines. |
Absagen, die nicht vom Token-Endpunkt selbst kommen, haben dort dieselbe Form; code ist dann der Code aus der Tabelle oben:
| Fall | HTTP | error | code |
|---|---|---|---|
| Zu viele Token-Abrufe, zu viele abgewiesene Anmeldungen oder zu viele Anfragen von Ihrer Adresse | 429 | invalid_request | RATE_LIMITED |
| Anfragen von Ihrer Adresse gesperrt | 403 | invalid_request | IP_BLOCKED |
| Rumpf unlesbar oder zu groß | 400, 413, 415 | invalid_request | INVALID_JSON, INVALID_REQUEST, PAYLOAD_TOO_LARGE, UNSUPPORTED_MEDIA_TYPE |
| Wartung | 503 | temporarily_unavailable | MAINTENANCE |
| Fehler auf unserer Seite | 500 | server_error | INTERNAL_ERROR |
#Grenzen
| Was | Grenze | Anmerkung |
|---|---|---|
| Anfragen je Zugang | 600 je Minute | darüber 429 mit Retry-After; RateLimit-* zeigt den Spielraum |
| Spitzen je Zugang | 50 je Sekunde | auch innerhalb der Minutengrenze |
| Token-Abrufe | 30 je Minute | je client_id; ein Token gilt 1 h |
| Abgewiesene Anmeldungen je Adresse | 30 je Minute | schützt vor dem Raten von Schlüsseln |
| Webhook-Endpunkte | 10 je Umgebung | Echtbetrieb und Sandbox getrennt |
| Antwortzeit Ihres Webhook-Endpunkts | 10 s | danach gilt der Versuch als gescheitert |
| Zeitstempel einer Webhook-Nachricht | ± 5 min | ältere Nachrichten verwerfen |
| Textfelder | 500 Zeichen | externalOrderId und Idempotency-Key: 200 |
| Sandbox: Vorgänge | 500 je Tag | je Mandant |
| Sandbox: automatischer Schritt | alle 20 s | mit X-Sandbox-Mode: manual von Hand |
| Sandbox: Aufbewahrung | 30 Tage | danach werden Testvorgänge gelöscht |
Die Köpfe RateLimit-Limit, RateLimit-Remaining und RateLimit-Reset jeder Antwort zeigen, wie viel Spielraum bleibt. Wird es knapp, verteilen Sie Aufrufe gleichmäßiger, statt sie gesammelt zu schicken — und nutzen Sie Webhooks, statt den Stand in kurzen Abständen abzufragen.
Hinweis
Braucht Ihre Anbindung dauerhaft mehr, sprechen Sie uns an.