ProductInformationBlogAboutContactOpen App
Documentation

Merchant API Documentation

Container recommendation API · v1

Compare your available containers using item dimensions, quantities and packing constraints. Single-SKU requests return arranged packing data. Mixed-SKU requests return volume and dimension estimates.

Base URL: https://optipacker.com/api/v1

Authentication

Obtain the current ID token from your authenticated Optipacker session and pass it in the header. Refresh expired tokens through Firebase Authentication.

Authorization: Bearer your_firebase_id_token

Endpoints

POST /optimal-container

Calculates the best container from a provided list for a given set of items.

Minimal Request Body
{ "availableContainers": [ { "sku": "BOX-1", "name": "Small", "innerDimensions": { "length": 200, "width": 150, "height": 100 }, "maxWeight": 2000 } ], "items": [ { "sku": "ITEM-1", "name": "Widget", "dimensions": { "length": 50, "width": 50, "height": 50 }, "weight": 100, "quantity": 1 } ] }
Advanced Request Body (Visualization Enabled)

For single-SKU 3D coordinates, use algorithm: "arranged" in options. Arranged is the default algorithm.

packingMode: "shipment" is the default. It packs up to the requested quantity. Use packingMode: "capacity" to estimate how many copies of one item type fit under the supplied constraints. Capacity mode can return more items than the requested quantity and requires a single SKU. The capacity is the layout found by the algorithm.

This endpoint supports arranged packing. Bulk, hybrid and maxVoidPercentagerequests return a validation error. Shipment mode supports stable stacking (the default) or sequential stacking. Even and balanced stacking are available in capacity mode.

Set layerPattern: "identical_layers" for centered rectangular layers with the same item positions in every layer. This requires a single SKU, shipment mode, stable stacking, strict gaps and at most 10,000 requested items. The calculation checks permitted rotations and prefers fewer layers when they pack the same quantity. If complete layers cannot hold the requested quantity, the result reports the packed count and a partial-fit reason. This option omits capacity. Supported gap fields are x, y, z, sideWallClearance, bottomClearance, wallClearance and enforcementMode. Other gap overrides return a validation error.

{ "availableContainers": [...], "items": [...], "options": { "algorithm": "arranged", "packingMode": "shipment", "gaps": { "sideWallClearance": 10, "bottomClearance": 10, "x": 5, "y": 5, "z": 2 }, "rotationConstraints": { "allowXAxisRotation": false } } }

Response Format

The API ranks the submitted containers, prioritizing full fits and then lower void fraction. It returns a recommendation and up to three alternatives. A successful response may contain a partial fit: check fitsAllItems, itemCount and unpackedItems before using the recommendation.

itemCount is the number represented by the result; single-SKU arranged results contain that many placements. requestedItemCount preserves the submitted quantity, and capacity reports the calculated single-SKU capacity. fitsAllItemsindicates whether the container can accommodate the requested shipment.

efficiency is occupied item volume divided by the container's internal volume, on a 0–1 scale. voidPercentage is its complement on the same scale. Both describe the packed items. totalContentWeight is their weight in grams;totalGrossWeight adds container tare. Placement positions are part centres in millimeters from the minimum inner container corner: X is length, Y is width and Z is height. Dimensions include rotation. Mixed-SKU results use a volume and dimension estimate and do not include placements or capacity.

Example fit for six 20 × 20 × 20 mm items weighing 10 g each, in a 300 × 200 × 150 mm container with 150 g tare. Placement details are omitted from this excerpt.

{ "success": true, "recommendation": { "container": { ...container_details }, "fit": { "containerSku": "DEMO-BOX", "packingMode": "shipment", "requestedItemCount": 6, "fitsAllItems": true, "efficiency": 0.005333333333333333, "voidPercentage": 0.9946666666666667, "itemCount": 6, "totalContentWeight": 60, "totalGrossWeight": 210, "unpackedItems": [] } } }

Integration Use Cases

The Merchant API is designed for three primary integration scenarios. Each demonstrates how container optimization fits into existing logistics workflows.

E-Commerce Checkout Optimization

Send cart items and your box catalog to compare container options before checkout. Check that the recommendation fits the full order, then use your carrier integration to calculate the shipping rate. Mixed-SKU cart results are packing estimates.

// Typical checkout integration flow const cartItems = getCartItems(); const idToken = await signedInUser.getIdToken(); const response = await fetch("https://optipacker.com/api/v1/optimal-container", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${idToken}` }, body: JSON.stringify({ availableContainers: boxes, items: cartItems }) }); const result = await response.json(); if (!response.ok || !result.success) { throw new Error(result.error?.message ?? "Recommendation failed"); } const { recommendation } = result; if (!recommendation.fit.fitsAllItems) { throw new Error("Review the partial fit before shipping"); } displayShippingCost(recommendation.container);
Warehouse Pick-and-Pack

Add single-SKU packing layouts to your warehouse workflow. Arranged results provide item-centre coordinates and rotated dimensions for visualization or operator guidance. Your integration must account for the physical packing process. Mixed-SKU estimates do not include placement coordinates.

// Extract packing instructions from the response const placements = recommendation.fit.placements ?? []; placements.forEach(p => { console.log(`Place ${p.itemSku} at position (${p.position.x}, ${p.position.y}, ${p.position.z})`); });
Shipping Label Generation

Match the recommended container SKU to the external dimensions in your packaging catalog, then pass those dimensions and the shipment weight to your carrier integration. The packing API uses internal dimensions and does not calculate carrier rates or generate labels.

// Use container dimensions for carrier rate lookup const packageSpec = packagingCatalog[recommendation.container.sku]; const shipmentDims = { ...packageSpec.externalDimensions, // convert to your carrier's units weight: recommendation.fit.totalGrossWeight // grams }; const rate = await carrierApi.getRates(shipmentDims);

Error Responses

The API uses standard HTTP status codes and returns structured error objects with machine-readable codes, human-readable messages, and contextual details for debugging.

Status
Code
Description
400

INVALID_JSON

Request body is not valid JSON

400

INVALID_FORMAT

Input validation failed; inspect error.details.issues for missing fields, invalid values or unsupported options

401

UNAUTHORIZED

Missing, invalid or expired Firebase ID token

429

RATE_LIMITED

User rate limit reached; wait for the reset interval

500

INTERNAL_SERVER_ERROR

Unexpected calculation error or no container result could be calculated

Example Authentication Error
{ "success": false, "error": { "code": "UNAUTHORIZED", "message": "Missing authorization token" }, "requestId": "req_example" }

Rate Limiting

The authenticated endpoint allows 100 requests per minute per user. Requests are counted after token verification, including requests that subsequently fail input validation.

Scope
Limit

Authenticated user

100 requests / minute

Rate Limit Headers

Successful calculation responses and 429 responses include the following headers. Authentication and validation errors may omit them. X-RateLimit-Reset reports seconds remaining in the current window.

X-RateLimit-Limit: 100 // Max requests per window X-RateLimit-Remaining: 87 // Requests remaining in current window X-RateLimit-Reset: 42 // Seconds remaining until reset

Versioning

The current API uses the /api/v1/ URL path. Review this reference when updating an integration.

  • Current endpoint: POST /api/v1/optimal-container

  • API versioned via URL path — current base: /api/v1/

  • Handle HTTP errors and successful partial-fit responses separately.

  • Accept additional response fields and treat optional fields, including placements and capacity, as optional.

Last updated: