Packfit API
Ein Endpunkt. Sie senden Artikel und Kartons und erhalten den Packplan, die gewählten Kartons und das abrechnungsrelevante Volumengewicht. Neu hier? Beginnen Sie mit dem Schnellstart.
Authentifizierung
Jede Anfrage trägt einen Bearer-Key. Keys sind an eine Umgebung gebunden: pf_test_… für die Entwicklung, pf_live_… für die Produktion. Wir speichern nur einen HMAC Ihres Keys — ein verlorener Key lässt sich nicht wiederherstellen, nur ersetzen.
Authorization: Bearer pf_live_xxxxxxxxxxxxxxxxxxxxxxxxPOST /v1/pack
Einheiten sind ganze Millimeter und ganze Gramm. Ganze Zahlen halten die Packung deterministisch; mit Fließkomma-Maßen könnten zwei Server unterschiedlich beurteilen, ob ein Artikel passt.
Anfrage
| items[]erforderlich | array | Die zu packenden Einheiten. Artikelfelder siehe unten. |
| cartons[]erforderlich | array | Ihr verfügbares Kartonsortiment. Der Packer wählt ausschließlich daraus — er erfindet nie einen Karton. |
| dimWeight | object | divisorCm3PerKg (z. B. 5000) und optional roundUpToKg (Standard 0,5). Weglassen, um die Berechnung des Volumengewichts zu überspringen. |
| maxCartons | integer | Obergrenze für Pakete, Standard 50. Artikel, die dann nicht mehr passen, erscheinen in unpacked. |
| rateCards[] | array | Frachttarife (carrierId, divisorCm3PerKg, Gewichts-brackets, optional surchargePerParcelCents und Größengrenzen). Übergeben, minimiert der Packer echtes Geld und nennt je Paket den günstigsten Frachtführer; ohne Angabe minimiert er Volumengewicht plus einen Zuschlag je Paket. |
| effort | enum | auto (Standard), fast oder thorough. Steuert, wie viele Packstrategien geprüft werden. auto rechnet bis 60 Einheiten gründlich. |
Artikelfelder
| skuerforderlich | string | Ihre Kennung. Wird bei jeder Platzierung zurückgegeben. |
| lengthMm / widthMm / heightMmerforderlich | integer | Außenmaße einer Einheit. |
| weightGerforderlich | integer | Gewicht einer Einheit. |
| quantity | integer | Standard 1. Wird intern in einzelne Einheiten aufgelöst. |
| nonStackable | boolean | Auf diesem Artikel darf nichts platziert werden. |
| thisSideUp | boolean | Beschränkt die Drehung auf die Hochachse — der Artikel wird nie auf die Seite gelegt. |
| maxStackWeightG | integer | Grenzlast: zulässiges Gesamtgewicht, das über diesem Artikel liegen darf. |
| hazmat | enum | ADR-Klasse, z. B. class3_flammable_liquids. Nicht zusammenladbare Klassen werden auf verschiedene Kartons verteilt. |
| tempRegime | enum | ambient | chilled | frozen. Temperaturbereiche teilen nie einen Karton. |
| warehouse | string | Herkunftslager, Standard default. Artikel aus verschiedenen Lagern teilen nie einen Karton — jedes Lager wird ein eigener Eintrag in shipments. |
Kartonfelder
| iderforderlich | string | Ihre Kartonkennung, wird als cartonId zurückgegeben. |
| innerLengthMm / innerWidthMm / innerHeightMmerforderlich | integer | Nutzbare Innenmaße. |
| maxPayloadGerforderlich | integer | Maximales Inhaltsgewicht, ohne Leergewicht. |
| tareWeightG | integer | Leergewicht des Kartons, wird auf Brutto- und Volumengewicht addiert. |
| costCents | integer | Verpackungskosten, summiert in packagingCostCents. |
| enabled | boolean | Auf false setzen, um einen Karton auszuschließen, ohne ihn aus Ihrem Katalog zu löschen. |
Antwort
{
"cartons": [
{
"cartonId": "M",
"placements": [
{ "sku": "PAN", "x": 0, "y": 0, "z": 0,
"lengthMm": 240, "widthMm": 240, "heightMm": 60,
"weightG": 1450, "orientation": 0 }
],
"grossWeightG": 6690,
"contentWeightG": 6470,
"fillRate": 0.64,
"billableWeightG": 7000,
"tempRegime": "ambient",
"hazmatClasses": [],
"valueCents": 0
}
],
"unpacked": [],
"packagingCostCents": 55,
"totalGrossWeightG": 6690,
"totalBillableWeightG": 7000,
"inputFingerprint": "12zzv44c",
"trace": ["12 units expanded, sorted by decreasing volume", "opened carton M for PAN"]
}x, y, z ist die minimale Ecke des Artikels im Karton; lengthMm/widthMm/heightMm sind die Maße nach der Drehung — Sie können damit direkt rendern oder eine Packanweisung ausgeben. inputFingerprint ist ein stabiler Hash der Anfrage: gleiche Eingabe ergibt immer denselben Plan, der Wert taugt also als Cache-Key.
Fehler
| 400 | bad request | Der Body war kein gültiges JSON. |
| 401 | unauthorized | Key fehlt, ist fehlerhaft, unbekannt oder widerrufen. |
| 402 | payment required | Monatliches Kontingent in einem Tarif ohne Überverbrauch aufgebraucht. Upgrade durchführen oder auf die nächste Periode warten. |
| 405 | method not allowed | Bitte POST verwenden. |
| 422 | unprocessable | Gültiges JSON, aber keine packbare Aufgabe — etwa ein Schemaverstoß wie ein negatives Maß. Das Kontingent wird nicht belastet. |
| 429 | too many requests | Ratenbegrenzung des Keys erreicht. Retry-After beachten. |
| 503 | unavailable | Deployment nicht vollständig konfiguriert (Datenbank oder Billing). |
Artikel, die physisch nicht platziert werden können, sind kein Fehler: Sie kommen mit Begründung in unpacked zurück, damit eine Teilbestellung trotzdem versandfertig ist.
Kontingente und Ratenbegrenzung
| Tarif | Berechnungen / Monat | Anfragen / Min. | Überverbrauch |
|---|---|---|---|
| Free | 0 | 60 | harte Grenze |
| Trial | 250 | 60 | harte Grenze |
| Starter | 1.000 | 120 | wird abgerechnet |
| Growth | 50.000 | 600 | wird abgerechnet |
| Scale | 500.000 | 3.000 | wird abgerechnet |
Jede Antwort enthält die Header Packfit-Quota-Limit, Packfit-Quota-Used, Packfit-Quota-Remaining und RateLimit-* — ein Client kann sich also ohne zweite Anfrage selbst drosseln.
Determinismus und Datenschutz
Der Endpunkt ist zustandslos: Ihre Maße, SKUs und Kartondaten werden im Speicher berechnet und mit der Antwort verworfen. Dauerhaft gespeichert wird nur ein monatlicher Anfragezähler — siehe Datenschutzerklärung.