Zum Inhalt springen
Cargo Marshal
Esc
↑↓navigieren↵öffnen⌘Jvorschau
Auf dieser Seite

Persistenz-API

Ein Project anlegen, Fracht importieren, eine Berechnung starten und den gespeicherten Ladeplan lesen.

Die Persistenz-API ist REST unter /api/v1 auf dem Origin der App, zum Beispiel https://app.example.com/api/v1. Das OpenAPI-3.1-Dokument liegt unter /api/v1/spec.json, und /api/v1 selbst zeigt die Scalar-Referenz, in der Sie jede Route ausprobieren können. Für Postman importieren Sie /api/v1/postman.json, und der API-Schnellstart zeigt den ganzen Ablauf. Das ist nicht der Cookie-Baum /rpc und nicht die Admin-Referenz unter /api-reference.

Jede Route, jedes Feld und jeder Fehlercode unten wird aus einem Vertrag erzeugt, daher entspricht die Spezifikation unter /api/v1/spec.json immer dem Verhalten des Servers. Erzeugen Sie Ihren Client daraus, statt Strukturen von Hand abzuschreiben.

Authentifizierung

Senden Sie bei jeder Anfrage einen API-Schlüssel der Organisation als Bearer-Token:

Authorization: Bearer sc_live_…

Das Geheimnis wird in der App unter API-Schlüssel einmal angezeigt, und gespeichert wird nur ein Hash. Inhaber und Admins können ihn rotieren oder widerrufen. Ein widerrufener oder rotierter Schlüssel funktioniert sofort nicht mehr. Ein Schlüssel handelt nur für seine Organisation: Ids einer anderen Organisation antworten mit 404, als gäbe es sie nicht.

Scopes

Jeder Schlüssel hat einen von zwei Scopes, den Sie beim Erstellen wählen:

  • Lesen und schreiben (read_write, der Standard) ruft jede Route auf.
  • Nur lesen (read) ruft nur die GET-Routen auf: ein Project, seine Fracht, einen Ladeplan oder eine Berechnung lesen und die Bibliotheken auflisten. Jede andere Route antwortet mit 403, code: "FORBIDDEN" und data.reason: "insufficient_scope", bevor etwas geändert wird.

Schlüssel, die vor den Scopes erstellt wurden, haben Lese- und Schreibzugriff. Beim Rotieren behält ein Schlüssel seinen Scope.

Ablauf

Ein Schlüssel läuft nie ab, außer Sie legen beim Erstellen einen Ablauf fest: in 30 Tagen, 90 Tagen oder einem Jahr (die API erlaubt höchstens zwei Jahre im Voraus). Ab diesem Zeitpunkt antwortet der Schlüssel wie ein widerrufener mit 401. Rotieren Sie einen Schlüssel mit Ablauf, erhält der neue Schlüssel eine neue Laufzeit gleicher Länge; so macht eine Rotation auch einen abgelaufenen Schlüssel wieder nutzbar.

Von wem der Schlüssel abhängt

Ein Schlüssel bleibt nur gültig, solange das Mitglied, das ihn erstellt hat, noch in der Organisation ist und noch Inhaber oder Admin ist, also eine Rolle hat, die API-Schlüssel verwalten darf. Verlässt dieses Mitglied die Organisation, wird es entfernt oder zu Mitglied oder Betrachter herabgestuft, antwortet jeder Schlüssel, den es erstellt hat, mit 401. Der Schlüssel wird nicht auf Nur-Lesen herabgestuft, sondern gesperrt. Ein Inhaber oder Admin erstellt dann einen neuen Schlüssel.

Ein fehlender, fehlerhafter, widerrufener, abgelaufener oder unbekannter Schlüssel, oder einer, dessen Ersteller die Bedingung nicht mehr erfüllt, antwortet mit 401, code: "UNAUTHORIZED" und dem Header WWW-Authenticate: Bearer realm="api". Die Antwort ist in jedem Fall gleich und verrät nicht, welche Prüfung fehlschlug; der Grund wird serverseitig im API-Audit-Protokoll festgehalten (siehe Audit-Protokoll).

API-Zugang gibt es nur mit Enterprise (apiAccess). Andere Pläne erhalten 403 mit code: "FORBIDDEN". Die Pläne, die heute verkauft werden, setzen dieses Flag nicht, bis der Enterprise-Katalog live ist.

Die API ist für Server-zu-Server-Aufrufe gedacht. Behalten Sie den Schlüssel auf Ihrem Server und rufen Sie die API nicht aus einem Browser auf. Cross-Origin-Anfragen aus dem Browser anderer Websites sind nicht erlaubt, und /api/v1 sendet und akzeptiert nie ein Cookie.

Was ein Schlüssel kann

Methode Pfad Wirkung Erfolg
POST /projects Ein Project anlegen 201
GET /projects/{projectId} Ein Project mit seinen Load-Plan-Köpfen lesen 200
POST /projects/{projectId}/load-plans Einen Ladeplan anlegen 201
POST /projects/{projectId}/cargo Frachtzeilen importieren 201
GET /projects/{projectId}/cargo Die Frachtzeilen des Projects auflisten 200
PATCH /load-plans/{loadPlanId}/equipment Der Laderaum des Ladeplans ändern 200
POST /load-plans/{loadPlanId}/calculate Eine Berechnung einreihen 202
GET /calculates/{id} Einen Berechnungslauf lesen 200
POST /calculates/{id}/cancel Einen Berechnungslauf abbrechen 200
GET /load-plans/{id} Den gespeicherten Ladeplan lesen, mit Placements 200
POST /load-plans/{loadPlanId}/share-links Einen rein lesenden Freigabelink erzeugen 201
GET /libraries/cargo Die Cargo Library auflisten 200
GET /libraries/equipment Laderaum-Typen auflisten, inkl. Sea- und Road-Typen 200
  • Frachtzeilen liegen schon in Millimetern und Gramm vor. Eine Zeile kann einen groupKey tragen: Zeilen mit demselben Schlüssel sind eine Gruppe, die als ein Block in eine Ladeeinheit geladen oder als Ganzes mit dem Grund group-does-not-fit nicht verladen wird. Ein Import von bis zu 5.000 Zeilen ist eine Transaktion: Er wird ganz oder gar nicht angehängt.
  • Eine Zeile kann eine stop (Entladestelle) tragen, eine ganze Zahl von 1 bis 99 oder null, beim Schreiben optional. Entladestelle 1 wird zuerst entladen, und eine Zeile ohne Entladestelle wird nach allen Entladestellen entladen. Ein Projekt kann stops tragen, ein Array aus {stop, name} mit eindeutigen, aufsteigenden Ordnungszahlen, beim Schreiben optional. Die Namen sind nur Bezeichnungen. Projektdateien tragen dieselben optionalen Felder, und ältere Dateien lassen sich weiterhin importieren.
  • Eine Zeile kann minSupportPermille tragen, eine ganze Zahl von 501 bis 1000 oder null, beim Schreiben optional. Es ist der Mindestanteil der Grundfläche des Stücks in Promille, der auf direkt darunterliegender Ladung aufliegen muss, wenn es nicht auf dem Boden steht. null und weggelassen bedeuten beides 1000, volle Auflage. Bibliothekseinträge und Projektdateien tragen dasselbe optionale Feld, und ältere Dateien lassen sich weiterhin importieren.
  • Eine Zeile kann frictionSurface tragen, worauf ihre Stücke für die Ladungssicherungsprüfung stehen: eines von wood_on_wood, planed_wood_on_wood, wood_on_steel, plastic_on_wood, plastic_on_metal, steel_on_wood, steel_on_steel und rubber_mat, oder null, beim Schreiben optional. null und weggelassen bedeuten beides die Standard-Reibung des Ladeplans. Bibliothekseinträge und Projektdateien tragen dasselbe optionale Feld, und ältere Dateien lassen sich weiterhin importieren.
  • Ein Ladeplan in einer Projektdatei kann securing tragen, die Transportabschnitte, für die er die Ladungssicherung prüft: {"legs": [...]} mit einem oder mehreren von road, rail, sea-a, sea-b und sea-c und einem optionalen frictionPermille von 1 bis 1500. null und weggelassen bedeuten beides keine Prüfung, daher lassen sich ältere Dateien weiterhin importieren. Wurde das gespeicherte Ergebnis einer Datei gegen andere Abschnitte geprüft, wird es beim Import gegen die Abschnitte des Plans neu geprüft.
  • Laderaum-Ids stammen aus GET /libraries/equipment, inklusive der eingebauten Sea- und Road-Typen.

Projects und Fracht lesen

GET /projects/{projectId} liefert die Metadaten des Projects, cargoLineCount und je Ladeplan einen Kopf, der älteste zuerst: id, name, revision, stale, solvedAt (null vor der ersten Berechnung), createdAt und updatedAt. Fracht, Laderaum und Placements sind nicht enthalten; Laderaum und gespeichertes Ergebnis eines Ladeplans liest GET /load-plans/{id}.

GET /projects/{projectId}/cargo liefert die Frachtzeilen des Projects seitenweise in Grid-Reihenfolge, also in der Reihenfolge, in der sie importiert oder in der App angeordnet wurden. Jeder Eintrag hat jedes Feld, das eine Importzeile nimmt, mit ausgefüllten Standardwerten (rotation: "free", stackable: true, fragile: false) und fehlenden Werten als null, dazu id, revision, sourceLibraryItemId (gesetzt, wenn die Zeile aus der Cargo Library stammt), createdAt und updatedAt. Um Fracht in ein anderes Project zu kopieren, lassen Sie diese zusätzlichen Felder weg und senden den Rest an POST /projects/{projectId}/cargo.

Einheiten und Formate

Längen sind ganze Millimeter (lengthMm, innerWidthMm, …), Gewichte ganze Gramm (weightG, maxPayloadG, …). Zeitpunkte sind RFC-3339-Strings in UTC, Kalenderdaten YYYY-MM-DD. Request-Bodies sind JSON mit Content-Type: application/json und höchstens 4 MB groß; ein größerer Body antwortet mit 413. Unbekannte Schlüssel im Request-Body ergeben 400. Antworten können neue Felder bekommen; ignorieren Sie Felder, die Sie nicht kennen.

Laderaum

PATCH /load-plans/{loadPlanId}/equipment führt eine Änderung mit dem Laderaum des Ladeplans zusammen:

  • equipmentTypeIds ist die vollständige Menge der gewählten Laderaum-Typen aus der Bibliothek. Ein weggelassener Typ wird abgewählt.
  • maxUnitsByEquipmentTypeId setzt optional die Höchstzahl an Ladeeinheiten pro gewähltem Typ (null heißt ohne Grenze). Ein gewählter Typ, den Sie weglassen, behält seine Grenze.
  • Laderaum ohne Bibliothekstyp (importiert, oder dessen Typ gelöscht wurde) bleibt, außer seine Id steht in removeEquipmentIds. Eine Id, die nicht mehr am Plan hängt, wird ignoriert.
  • Gewählte Typen und verbleibendes Laderaum dürfen zusammen 20 Zeilen nicht überschreiten.

Senden Sie expectedRevision mit der revision Ihres letzten Lesens. Hat sich der Ladeplan inzwischen geändert, wird nichts gespeichert, und der Aufruf antwortet mit 412 und code: "PRECONDITION_FAILED"; data.conflicts nennt die Ressource mit expectedRevision und currentRevision. Lesen Sie erneut und wiederholen Sie den Aufruf. Die Antwort enthält die neue revision für Ihren nächsten Schreibaufruf.

Berechnung

Eine Berechnung nutzt denselben Optimierer wie Berechnen in der App und läuft im Hintergrund:

  1. GET /load-plans/{id} aufrufen und revision merken.
  2. POST /load-plans/{loadPlanId}/calculate mit {"expectedRevision": <revision>} senden. Gesperrte Placements bleiben immer erhalten. Hat jemand Stücke von Hand verschoben, ohne sie zu sperren, senden Sie "replaceUnlockedManual": true, damit der Lauf sie ersetzen darf; ohne das Flag antwortet der Aufruf mit 409, statt die manuelle Arbeit zu überschreiben. Ein gesperrtes Placement über dem Boden muss auf anderen gesperrten Placements stehen: Sonst antwortet der Aufruf mit 400 und einer Meldung, die das betroffene Stück nennt, weil der Solver nie ein freies Stück unter ein gesperrtes schiebt. Sperren dürfen auch keine Gruppe aufbrechen: Eine nur teilweise gesperrte Gruppe, gesperrte Stücke einer Gruppe in zwei Ladeeinheiten oder eine Sperre im Block einer anderen Gruppe ergeben ebenfalls 400 mit der Gruppe oder den betroffenen Stücken. Die App sperrt und entsperrt eine Gruppe immer als Ganzes. Die Antwort ist 202 mit der Lauf-id und status: "queued".
  3. GET /calculates/{id} abfragen oder Webhooks abonnieren und auf das Ereignis warten. status wechselt über queued und running (mit phase, processedItems und totalItems) zu completed, cancelled, failed oder timed_out. Ein fehlgeschlagener Lauf liefert einen failureCode, zum Beispiel revision_conflict, wenn sich der Ladeplan nach Ihrem Lesen geändert hat.
  4. Ist der Lauf completed, lesen Sie GET /load-plans/{id} erneut für die Placements. Der Lauf selbst meldet nur die neue revision und solvedAt.

Im gespeicherten Ergebnis listet warnings Regelverstöße, nicht geladene Ladung und den Schwerpunkt-Hinweis. Achslast-Hinweise für Straßen-Laderaum mit Achsprofil (axle-overload, axle-lift, steer-axle-underload, drive-axle-underload, gross-overload) stehen gesondert in axleWarnings; das Feld fehlt, wenn es keine gibt. Eine Entladestelle, deren Ladung unter Ladung einer späteren Entladestelle oder ohne Entladestelle steht oder vor jeder Öffnung, durch die sie hinaus könnte, wird als stop-blocked im optionalen Array stopWarnings gemeldet, neben warnings und axleWarnings. Die Liste warnings bleibt unverändert. Es ist nur eine Warnung, und ein Die Berechnung wird deswegen nie abgelehnt.

GET /load-plans/{id} liefert das securing des Plans: die Transportabschnitte, für die er die Ladungssicherung prüft, oder null für keine Prüfung. Die Abschnitte werden in der App gesetzt; die API liest sie nur. Hinweise zur Ladungssicherung (securing-unblocked und securing-tipping) stehen im optionalen Array securingWarnings des gespeicherten Ergebnisses; das Feld fehlt, wenn es keine gibt. Jeder Hinweis nennt eine Ladeeinheit, eine direction (forward, rearward oder sideways) und die zu sichernden Packstücke. Sie sind ein Hinweis und keine rechtliche Bewertung und stehen nie in warnings. Die Anleitung zur Ladungssicherung erklärt sie.

POST /calculates/{id}/cancel stoppt eine wartende oder laufende Berechnung. Ein abgebrochener Lauf schreibt keine Placements.

Pro Ladeplan läuft eine Berechnung zur Zeit: Ein zweites Einreihen, während eine wartet oder läuft, antwortet mit 409. Eine Organisation darf 10 Berechnungen gleichzeitig wartend oder laufend haben; die elfte antwortet mit 429.

Eine Berechnung unterstützt höchstens 10.000 Ladungspositionen, insgesamt 20.000 Stücke und 500 Ladeeinheiten. Ladung über einer dieser Grenzen wird mit 400 abgelehnt, bevor ein Lauf eingereiht wird; die Meldung nennt die Grenze und Ihren Wert. Die Ladeeinheit-Prüfung nutzt eine untere Schranke (Gewicht, Volumen und Bodenfläche über dem größten angebotenen Laderaum) und lehnt daher nur Ladung ab, die sicher mehr als 500 Ladeeinheiten braucht.

Webhooks

Sie müssen nicht abfragen. Eine Organisation im Enterprise-Plan kann unter Einstellungen → Webhooks HTTPS-Endpunkte registrieren und erhält einen signierten POST, wenn eine Berechnung endet: calculate.completed, calculate.failed oder calculate.cancelled. Der Body nennt Berechnung, Ladeplan und Project und enthält keine Plandaten. Nach calculate.completed rufen Sie für die Placements also weiterhin GET /load-plans/{id} auf. Die Zustellung erfolgt mindestens einmal und ohne feste Reihenfolge. Die Webhooks-Anleitung behandelt die Signaturprüfung, Wiederholungen und die Netzwerkregeln, und die Spezifikation listet die Ereignisse unter webhooks.

POST /load-plans/{loadPlanId}/share-links erzeugt einen Freigabelink, der nur das Ansehen erlaubt. Verlader-Links, deren Besucher Ladeschritte abhaken können, erstellen Sie in der App. Der Body ist optional; senden Sie {"expiresAt": "2026-12-31T23:59:59Z"} für einen Link, der abläuft, oder lassen Sie ihn weg für einen, der nie abläuft. Hat der Ladeplan noch kein gespeichertes Ergebnis, antwortet der Aufruf mit 400 und data.reason load_plan_not_calculated. Starten Sie zuerst eine Berechnung. Mit showLoadingSteps: false blenden Sie die schrittweise Beladung für Besucher aus; der Standard ist true. Das ist eine Darstellungsoption: Schrittseiten, Schrittbilder und die Spalte mit dem Ladeschritt entfallen, aber die Platzierungsliste im Bericht und das CSV behalten die Ladereihenfolge, und die Plandaten des Links enthalten weiter das vollständige Ergebnis.

token und url stehen nur in der Antwort, die den Link erzeugt hat: Gespeichert wird nur ein Hash des Tokens. Bewahren Sie beides auf, oder erzeugen Sie einen neuen Link, wenn es verloren ist.

Idempotenz

POST /projects, POST /projects/{projectId}/load-plans, POST /projects/{projectId}/cargo, POST /load-plans/{loadPlanId}/calculate und POST /load-plans/{loadPlanId}/share-links verlangen den Header Idempotency-Key: 1 bis 255 sichtbare ASCII-Zeichen ohne Leerzeichen (eine UUID passt). Ohne ihn antworten sie mit 400.

  • Eine Wiederholung mit demselben Schlüssel und demselben Body innerhalb von 24 Stunden liefert die erste Antwort mit demselben Status, statt ein zweites Project, einen zweiten Import, eine zweite Berechnung oder einen zweiten Freigabelink zu schreiben.
  • Derselbe Schlüssel mit einem anderen Body, oder während die erste Anfrage noch läuft, antwortet mit 409 und code: "CONFLICT".
  • Eine Anfrage, die fehlschlug, bevor etwas geschrieben wurde (zum Beispiel 400 oder 404), verbraucht den Schlüssel nicht; wiederholen Sie sie mit demselben Schlüssel.
  • Schlüssel gelten pro API-Schlüssel. Nach dem Rotieren beginnt der neue API-Schlüssel ohne gespeicherte Idempotency-Keys.
  • Ein wiederholter Freigabelink hat token und url auf null, weil das Token nie gespeichert wird.

PATCH für Laderaum und POST /calculates/{id}/cancel nehmen keinen Idempotency-Key: Das erste schützt expectedRevision, und zweimal abbrechen wirkt wie einmal abbrechen.

Seitenweises Lesen

GET /libraries/cargo, GET /libraries/equipment und GET /projects/{projectId}/cargo liefern eine Seite: { "items": [...], "nextCursor": "…" }. Übergeben Sie nextCursor als cursor für die nächste Seite; auf der letzten Seite ist er null. Ein cursor, der kein Eintrag der Liste ist, antwortet mit 404. Bei den Bibliotheken setzt limit die Seitengröße, 1 bis 100 (Standard 20), und query filtert nach einem Teilstring, ohne auf Groß- und Kleinschreibung zu achten. Bei Frachtzeilen ist limit 1 bis 500 (Standard 100), und totalCount zählt alle Zeilen des Projects.

Die Laderaum-Liste filtert außerdem nach mode (sea oder road) und nach ids, das auch für eine einzelne Id die Klammer-Schreibweise verlangt:

curl -sS "$ORIGIN/api/v1/libraries/equipment?ids[]=eqt_a&ids[]=eqt_b" \
  -H "Authorization: Bearer $CARGO_MARSHAL_API_KEY"

Limits

Limit Geltung Budget
Anfragen pro Client-IP, vor der Anmeldung 300 pro Minute
Anfragen pro API-Schlüssel 120 pro Minute
Berechnungen einreihen pro API-Schlüssel 30 pro 10 Minuten
Gleichzeitige Berechnungen pro Organisation 10 wartend oder laufend

Eine Anfrage über einem Limit antwortet mit 429, code: "TOO_MANY_REQUESTS" und einem Retry-After-Header in Sekunden (auch in data.retryAfter, wenn das Limit ihn kennt). Warten Sie so lange, bevor Sie es erneut versuchen. Eine wiederholte Berechnung (derselbe Idempotency-Key) verbraucht das Berechnungsbudget nicht.

Die Limits pro Schlüssel fallen geschlossen aus: Ist der Limiter in Produktion nicht erreichbar, antwortet der Aufruf mit 503, statt durchgelassen zu werden. Wiederholen Sie 503 mit Backoff.

Fehler

Jeder Fehler antwortet mit demselben JSON-Body:

{
  "defined": true,
  "code": "BAD_REQUEST",
  "status": 400,
  "message": "Input validation failed",
  "data": {
    "reason": "invalid_input",
    "issues": [
      {
        "path": ["body", "lines", 0, "lengthMm"],
        "message": "Too small: expected number to be >=1",
        "code": "too_small"
      }
    ]
  }
}

Entscheiden Sie anhand von code und, wo gesetzt, data.reason; message ist englischer Text für Menschen und kann sich ändern. defined: true heißt, der Fehler ist einer, den die Spezifikation für diese Route dokumentiert, mit data in der dokumentierten Form; defined: false ist ein unerwarteter Fehler, meist ein 500.

Status code Wann
400 BAD_REQUEST Ungültige Eingabe (data.reason invalid_input, data.issues listet höchstens 50 fehlgeschlagene Prüfungen), Ladung, die der Solver nicht annimmt, oder ein Freigabelink auf einem nicht berechneten Ladeplan (load_plan_not_calculated)
401 UNAUTHORIZED Fehlender, ungültiger, widerrufener oder abgelaufener API-Schlüssel, oder sein Ersteller ist nicht mehr Inhaber oder Admin
403 FORBIDDEN Der Plan der Organisation enthält keinen API-Zugang, oder ein Schlüssel mit Nur-Lesen hat eine schreibende Route aufgerufen (insufficient_scope)
404 NOT_FOUND Die Id gibt es in der Organisation des Schlüssels nicht, oder der Pfad ist keine Route
405 — Den Pfad gibt es für andere Methoden; der Header Allow nennt sie
409 CONFLICT Wiederverwendeter Idempotency-Key, eine bereits laufende Berechnung oder nicht gesperrte manuelle Placements
409 PLAN_LIMIT Ein Tariflimit für Projekte, Berechnungen oder Freigabelinks
412 PRECONDITION_FAILED expectedRevision ist veraltet
413 — Der Body ist größer als 4 MB
429 TOO_MANY_REQUESTS Ein Limit ist erreicht; siehe Retry-After
503 SERVICE_UNAVAILABLE Der Limiter oder ein anderer Dienst ist nicht erreichbar; mit Backoff wiederholen

Die Spezifikation nennt pro Route genau, welche dieser Codes sie liefern kann.

Ein Tariflimit antwortet mit 409, code: "PLAN_LIMIT" und data, das das Limit nennt:

{
  "reason": "plan-limit",
  "resource": "solves",
  "limit": 10,
  "planName": "Free"
}

resource ist projects, solves oder share-links.

Jede Antwort trägt einen Header x-request-id. Nennen Sie ihn, wenn Sie den Support kontaktieren; Sie können auch eine eigene x-request-id senden, die dann übernommen wird.

Audit-Protokoll

Der Server legt eine API-Audit-Zeile (Schlüssel, Operation, Status, Ressourcen-Id) an für:

  • jeden schreibenden Aufruf, auch eine Wiederholung mit demselben Idempotency-Key, ob er gelingt oder scheitert;
  • jeden lesenden Aufruf, der in der Operation scheitert, zum Beispiel ein 404 für die Id einer anderen Organisation;
  • jede Ablehnung eines bekannten Schlüssels: Rate-Limit (429), Nur-Lesen-Scope (403), Plan ohne API-Zugang (403) sowie ein abgelaufener Schlüssel oder einer, dessen Ersteller die Bedingung nicht mehr erfüllt (401).

Erfolgreiche Lesezugriffe (GET-Routen mit 200) werden nicht festgehalten: Sie ändern nichts, und Integrationen fragen sie regelmäßig ab. Ebenfalls nicht festgehalten werden Anfragen, die am Eingabeschema scheitern (400 mit invalid_input), unbekannte oder widerrufene Schlüssel und Anfragen, die das Limit pro IP ablehnt.

Was ein Schlüssel nicht kann

Ein Schlüssel kann keine Placements und keinen Solve-Snapshot senden: Der Body der Berechnung nimmt nur die erwartete Revision und das Flag für manuelle Placements, und Placements werden immer auf dem Server berechnet. Admin, Abrechnung, Chat, Anmeldung und Dateispeicher bleiben außerhalb dieser API.

Versionierung und Abkündigung

/api/v1 ist stabil. Innerhalb von v1 gibt es nur additive Änderungen: neue Routen, neue optionale Eingabefelder, neue Antwortfelder, neue Werte für code oder data.reason bei einem bestehenden Status. Bauen Sie Clients so, dass sie unbekannte Antwortfelder ignorieren.

Eine inkompatible Änderung (eine Route oder ein Feld entfernen oder umbenennen, eine optionale Eingabe zur Pflicht machen, einen Typ oder einen Erfolgsstatus ändern) erscheint unter einer neuen Version, /api/v2, und v1 funktioniert daneben weiter. Jede Änderung der Spezifikation wird vor der Auslieferung auf inkompatible Änderungen geprüft.

Bevor eine Route oder ein Feld entfernt wird, ist sie in der Spezifikation mit deprecated: true markiert. Jede Antwort einer abgekündigten Route, ob erfolgreich oder nicht, trägt:

  • Deprecation: true oder das Datum der Abkündigung in der Form @<Unix-Sekunden> nach RFC 9745, zum Beispiel Deprecation: @1790812800.
  • Sunset: das Datum der Entfernung als HTTP-Datum (RFC 8594), zum Beispiel Sunset: Thu, 01 Apr 2027 00:00:00 GMT, sobald es feststeht.
  • Link: <…>; rel="deprecation": die Seite, die die Umstellung erklärt, sobald sie veröffentlicht ist.

Das Sunset-Datum liegt mindestens 6 Monate nach der Ankündigung. Protokollieren Sie diese Header in Ihrem Client, damit eine Abkündigung nicht unbemerkt bleibt. Heute ist keine v1-Route abgekündigt.

Beispiel

curl -sS -X POST "$ORIGIN/api/v1/projects" \
  -H "Authorization: Bearer $CARGO_MARSHAL_API_KEY" \
  -H "Idempotency-Key: project-4401" \
  -H "Content-Type: application/json" \
  -d '{"name":"Hamburg 40HC"}'

Ersetzen Sie $ORIGIN durch die App-URL. Der Aufruf antwortet mit 201 und dem neuen Project.

War diese Seite hilfreich?