Prize Structure
How It Worked
Qualify Through the Game
Participants played the truck loading game and scored ≥50% packing density to receive an API key.
Play the Game →Build a Packing Agent
Teams used the REST API to send placements and receive game state, building their own understanding of the physics without a provided simulator.
Compete and Advance
Agents played random sequences. The top five on the public leaderboard advanced to a private evaluation of 50 held-out sequences.
Scoring
Your score is packing density — the fraction of usable truck volume you fill with boxes.
// Density formula
density = sum(box_volumes) / (max_x_reached × truck_width × truck_height)How the Competition Worked
The competition had two phases. The public leaderboard determined who advanced, and the private evaluation determined the final result.
Public Leaderboard
Participants could play up to 50 games per day in compete mode. Each game drew from the same box pool with a randomly shuffled sequence. Rankings used the interquartile mean (IQM) of each agent's most recent 50 compete games.
Private Evaluation
The top five from the public leaderboard played 50 held-out sequences that no one had seen before. The sequences were pre-generated and frozen, and every finalist played the same sequences in the same order with no retries.
Final scores used the interquartile mean (IQM) across all 50 private sequences. A score of ≥70% IQM density was required to qualify for the prize. This round focused on pure packing without robot reachability constraints, visibility concerns, or observation noise.
Validation
Before any prize is awarded, top submissions are validated:
Rules
Questions? Reach us at foresight-api-challenge@dexterity.ai
Leaderboard
View the final public rankings from the concluded 2026 challenge.
View Final Public Leaderboard →Overview
The Foresight Packing Challenge API is a REST service where your agent packs boxes into a truck, one at a time. You receive a box, choose where to place it (position + orientation), and get back the full post-placement state including physics-settled positions.
Modes
Truck Segment Dimensions
Endpoints
Start a new game session. Returns the truck config and first box.
Request Body
| Field | Type | Description |
|---|---|---|
| api_key* | string | Your API key |
| mode | string | Defaults to "compete". Use "dev" for testing |
Response
| Field | Type | Description |
|---|---|---|
| game_id | string | Unique game session ID |
| truck | object | Dimensions in meters: { depth, width, height } |
| current_box | object | First box: { id, dimensions, weight } |
| boxes_remaining | int | Number of boxes left in the queue |
| mode | string | Confirmed game mode |
/start will fail — call /stop on an existing game first. Use /my-games?status=in_progress to see what's currently active.Place the current box in the truck. Returns the updated state with physics-settled positions.
Request Body
| Field | Type | Description |
|---|---|---|
| game_id* | string | From the /start response |
| box_id* | string | Must match current_box.id |
| position* | [x, y, z] | Center position in meters |
| orientation_wxyz* | [w, x, y, z] | Rotation quaternion (auto-normalized) |
Response
| Field | Type | Description |
|---|---|---|
| status | string | "ok" or "terminated" |
| placed_boxes | array | All placed boxes with post-settle positions and orientations |
| current_box | object | null | Next box to place, or null if game over |
| boxes_remaining | int | Boxes left in the queue |
| density | float | Current packing density (your score) |
| game_status | string | "in_progress" or "completed" |
| termination_reason | string | null | Why the game ended (if it did) |
id matches current_box.id. You cannot skip or reorder boxes.Get the current state of a game. Useful for debugging or resuming after a crash.
Response
| Field | Type | Description |
|---|---|---|
| game_id | string | The game session ID |
| game_status | string | "in_progress" or "completed" |
| mode | string | "dev" or "compete" |
| boxes_placed | int | Number of boxes placed so far |
| boxes_remaining | int | Boxes left in the queue |
| density | float | Current packing density |
| placed_boxes | array | All placed boxes with current positions |
| current_box | object | null | Next box to place |
End a game early. Your score is the density at time of stopping.
Request Body
| Field | Type | Description |
|---|---|---|
| game_id* | string | The game session to stop |
| api_key* | string | Your API key |
Retrieve all your games and a summary of your stats. Requires your API key.
Query Parameters
| Field | Type | Description |
|---|---|---|
| api_key* | string | Your API key |
| mode | string | Filter by "dev" or "compete" |
| status | string | Filter by "in_progress" or "completed" |
Response
| Field | Type | Description |
|---|---|---|
| api_key | string | Your API key |
| display_name | string | null | Your display name |
| summary | object | Aggregate stats: total/completed/in-progress game counts, avg & best compete density, games today, daily limit |
| games | array | All matching games (newest first), each with game_id, mode, status, density, boxes_placed, total_boxes, termination_reason, timestamps |
Health check. Returns {"status": "ok"}.
Coordinate System
The truck uses a right-handed coordinate system with the origin at the front-bottom-left corner.
Z (up, height: 2.75m)
^
|
|
+---------> Y (width: 2.6m)
/
/
v X (depth: 2.0m, loading direction)| Axis | Direction | Range |
|---|---|---|
| X | Depth (loading direction, front → back) | 0 → 2.0 m |
| Y | Width (left → right) | 0 → 2.6 m |
| Z | Height (floor → ceiling) | 0 → 2.75 m |
Position
The position field is the center of the box. To place a box flush on the floor in the front-left corner:
// Box dimensions: [length, width, height] = [0.4, 0.3, 0.2]
"position": [0.2, 0.15, 0.1] // half-extents from originOrientation
Quaternion in [w, x, y, z] format. Common rotations:
| Rotation | Quaternion | Effect |
|---|---|---|
| Identity | [1, 0, 0, 0] | No rotation |
| 90° around Z | [0.707, 0, 0, 0.707] | Swap length ↔ width |
| 90° around Y | [0.707, 0, 0.707, 0] | Swap length ↔ height |
| 90° around X | [0.707, 0.707, 0, 0] | Swap width ↔ height |
Tips for Building Your Agent
Start with dev mode
Use "mode": "dev" while building. Boxes land exactly where you place them — no physics surprises. Switch to "compete" when you're ready to test against real physics and get on the leaderboard.
Use placed_boxes for planning
Every /place response includes the full placed_boxes array with post-physics positions. In compete mode, boxes may shift from where you placed them. Use the settled positions to compute valid placement locations for the next box.
Think about stability
Placing boxes without support underneath will cause them to fall and potentially topple the stack. If 3 or more boxes displace by more than 10cm, the game terminates with unstable.
Optimize rotations
Each box can be placed in 6 orientations (3 axes × 2 flips that matter). Trying all valid rotations for each box is a key optimization. A box that doesn't fit one way might fit perfectly rotated.
Rate limits
Interactive docs
Swagger UI is available at /docs for interactive API exploration.
Happy packing. We'll see you on the leaderboard.