Skip to content

Shipments and states

EasyPick tracks the shipment status and the physical compartment state separately. A webhook is an event announcing a change; it does not necessarily change the shipment status itself.

reserved -> loaded -> picked_up
| |
+----------+-> cancelled / expired / fault
Status Meaning
reserved A compartment is reserved, but loading has not been confirmed.
loaded The shipment is inside. Also inspect pickup_enabled.
picked_up Customer pickup is confirmed. The compartment may still be in cooldown.
cancelled The shipment was cancelled. If it was already loaded, the compartment awaits physical removal.
expired The reservation or pickup deadline expired. Loaded contents must be physically removed.
fault Terminal shipment status after an operation that could not be completed safely.

cancelled, expired, and fault are terminal statuses. Physically removing the contents does not move them to another shipment status.

Public GET /shipments/{shipment_id} responses and webhook payloads include compartment_state.

compartment_state Meaning
reserved The compartment is assigned to the shipment, but loading has not been confirmed.
occupied The compartment physically contains the shipment.
awaiting_removal The shipment is terminal, but an operator must physically remove the contents.
cooldown Pickup is confirmed, but the compartment is waiting for operational release.
available The compartment is actually free and can be reserved for another shipment.
shipment creation: available -> reserved
loading: reserved -> occupied
empty reservation: reserved --door_available--> available
terminal after loading: occupied -> awaiting_removal
physical removal: awaiting_removal --removed + door_available--> available
pickup: occupied -> cooldown --door_available--> available

The removed event confirms physical removal from a compartment in awaiting_removal. The following door_available event confirms its actual release. Neither event changes the terminal shipment status.

After first loading, the status immediately becomes loaded, but pickup_enabled remains false during the protection period. The loader can reopen the compartment with the same PIN to correct its contents. Notify the customer only after receiving the loaded webhook: EasyPick delays it until the protection period has ended and the door is confirmed closed.

POST /shipments
Content-Type: application/json
Authorization: Bearer {api_key}
{
"box_id": "box_01k3example",
"external_order_id": "ORDER-2026-1042",
"customer_name": "Jane Smith",
"reservation_ttl_minutes": 1440,
"pickup_ttl_minutes": 4320
}

TTL fields are optional. The selected box settings apply when they are omitted.

GET /shipments/{shipment_id}

The response includes compartment_state in addition to status. Do not use the shipment status as the only signal that the compartment can be assigned again. The status endpoint does not return the PIN. Use GET /shipments/{shipment_id}/pickup-pin for an audited reveal.

POST /shipments/{shipment_id}/cancel

A reserved or loaded shipment can be cancelled. Repeating a cancellation is idempotent.

  • An empty reservation immediately moves to compartment_state=available, and EasyPick emits door_available.
  • A loaded shipment moves to status=cancelled, but the compartment remains in compartment_state=awaiting_removal. An operator must physically remove its contents; only removed followed by door_available confirms release.

fault is a terminal shipment status, not an automatic compartment release. The standard safe recovery flow is:

  1. The operator selects open for removal.
  2. The box confirms the closed -> open -> closed sensor cycle.
  3. The operator confirms that the compartment is empty.
  4. EasyPick emits removed followed by door_available; the shipment remains fault, while the compartment moves to available.

Use emergency release only after physically checking that the compartment is empty. Skipping this check can cause the system to assign a compartment that still contains goods.

POST /shipments/{shipment_id}/retry
Authorization: Bearer {api_key}

This endpoint is available only for a shipment in fault whose original compartment has actually been released (compartment_state=available). It creates a new attempt with the same external_order_id, reserves a currently available compartment, and generates a new PIN. The original shipment remains in fault for audit purposes.

The operation is idempotent with respect to the original faulted shipment ID. Repeated calls return the same new attempt and the same new PIN; they do not create additional reservations.

The original POST /shipments remains idempotent to its first request: repeating it with the same external_order_id returns the first attempt. Always use /retry after a fault and persist the returned replacement shipment ID.

The only public state confirming that another reservation is possible is compartment_state=available. The door_available webhook is the canonical event after every actual compartment release:

  • after the normal post-pickup cooldown,
  • after removed for a loaded shipment in cancelled, expired, or fault,
  • after immediately releasing a reservation that was never loaded.

door_available does not change the shipment status.