Loader4D API
Call load optimisation from inside your own ERP, WMS or transport management system. The same placement engine that runs in the browser, behind a single HTTP request.
What you can do
Send your spaces and item list as JSON and get the placement plan back with the coordinates of every piece. Axle loads and items that could not be placed are in the response too.
An optimisation takes seconds. In a synchronous design a dropped connection destroys the result; here you come back with the job id and collect it, so you never pay for the same computation twice.
Credits are banded, not per piece. The engine spends the same search budget on a small shipment as on a large one, so per-piece pricing would penalise small calls and make your bill impossible to forecast.
Test keys return real results and spend no credits; they are capped at 25 calls a month. Keep testing until your integration is done — going live only means swapping the key.
Endpoints
Authentication uses a bearer header carrying your key. Keys are never accepted in a query string.
Authorization: Bearer l4d_live_...
| Call | What it does |
|---|---|
| POST /api/v1/pack | Opens a placement job; returns 202 and a job id. |
| GET /api/v1/jobs/{id} | Returns the state of the job, and its result once finished. |
| GET /api/v1/usage | Returns your quota for the period and the credits left. |
Example request
Lengths are centimetres and weights are kilograms. There is no per-request unit setting; convert on your side. A request sent in inches loads a lorry ten times too long.
POST /api/v1/pack
Authorization: Bearer l4d_test_...
Content-Type: application/json
Idempotency-Key: 7f3c1a9e4b6d4c2f
{
"reference": "SO-2026-4417",
"spaces": [
{ "id": "sp1", "name": "40HC", "type": "container",
"length": 1200, "width": 235, "height": 269,
"max_weight": 26000, "available": 2 }
],
"items": [
{ "id": "A1", "name": "Karton", "length": 120, "width": 100, "height": 40,
"weight": 8, "quantity": 24, "group": "Siparis-1",
"constraints": { "no_tilt": true } },
{ "id": "B1", "name": "Varil", "shape": "cylinder",
"diameter": 58, "length": 88, "weight": 190, "quantity": 12,
"constraints": { "floor_only": true } }
],
"strategy": { "group_items": true, "balance_load": true }
}
The response comes back immediately; you poll the job id for the result.
HTTP/1.1 202 Accepted
Location: /api/v1/jobs/ba7189d3b1824da3806ca3ee973b2294
{ "id": "ba7189d3...", "status": "queued", "progress": 0,
"reference": "SO-2026-4417", "credits": 1 }
When the job finishes, every piece arrives with its coordinates. The origin is the front-left-bottom corner of the space, and the value given is that corner of the piece, not its centre.
{ "id": "ba7189d3...", "status": "succeeded", "credits": 1,
"result": {
"summary": { "spaces_used": 1, "pieces_requested": 36,
"pieces_packed": 36, "weight": 2472,
"volume_utilization": 0.7431 },
"spaces": [
{ "space_id": "sp1", "name": "40HC",
"placements": [
{ "item_id": "A1", "sequence": 1,
"x": 0, "y": 0, "z": 0,
"length": 120, "width": 100, "height": 40, "weight": 8 }
],
"axle_loads": [] }
],
"unpacked": []
} }
Credits and limits
Credits are deducted when a job is accepted, not when it finishes. Otherwise a hundred calls arriving at once would all pass the quota check before a single one had been counted.
| Total pieces in the request | Credits |
|---|---|
| 1 – 100 | 1 |
| 101 – 1 000 | 5 |
| 1 001 – 10 000 | 25 |
| 10 001 and above | 100 |
- At most 50 spaces per request.
- At most 2 000 item lines per request.
- At most 20 000 pieces in total per request.
- At most 10 active keys per team.
These limits exist so that one call cannot occupy the service for minutes. If your workload needs more, split it or get in touch.
Frequently asked
Which language can I integrate with?
Any language that can make an HTTP request. You can also download our OpenAPI 3.0 document and generate a typed client in most languages; that is the difference between an integration that takes hours and one that takes days.
How does pricing work?
The API is part of the paid plans; live calls require a credit pack, which renews each period. Unused credits do not carry over. Trying it out needs no credits: a test key allows 25 calls a month.
How are my keys protected?
A key is shown once, when it is created; only an encrypted digest is kept in the database. Keys belong to the team rather than to a person, so your integration keeps working even if whoever set it up leaves. Give each integration its own key; then if one is exposed you revoke only that one and the others keep running.
What if I send the same request twice by accident?
Send an Idempotency-Key header with a value you generate per logical request. A retry with the same key and the same body returns the original job instead of opening a second one. Using the same key with a different body is rejected: silently returning the earlier answer would leave you waiting for work that was never queued.
Does an interrupted job resume where it stopped?
No, and it is right to say so plainly. The search is a single computation and no intermediate state is kept; a failed job runs from the start. What the job id gives you is not continuity but the fact that the result is not lost.
Can I also see the results in the interface?
Jobs opened through the API are independent and are not added to your project list; the result comes back in the response. API calls spend credits rather than seats, so they do not affect the seats of team members using the interface.