Skip to main content

Basic LPN Validation

This is a simple example of validating an LPN (License Plate Number) on an order.

info

The following example uses Python for reference, but an integration can be built in any language or framework that can make HTTP requests and receive webhooks.

The Flow

  1. You create a shipment with an order containing expected LPNs
  2. As pallets pass through the Kargo vision system, you receive webhook events
  3. You validate that each scanned LPN matches what was expected on the order

Step 1: Get Access Token

Request:

POST https://mykargo.us.auth0.com/oauth/token
Content-Type: application/json
{
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"audience": "https://api.kargo.zone/public_graphql",
"grant_type": "client_credentials"
}

Response:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 86400,
"token_type": "Bearer"
}
note

Cache your access token! Tokens are valid for 24 hours. Only request a new token when the current one expires.


Step 2: Create Shipment and Order

Request:

POST https://api.kargo.zone/public_graphql
Authorization: Bearer <access_token>
Content-Type: application/json

GraphQL Mutation:

mutation CreateShipmentAndOrder($input: CreateShipmentAndOrderInput!) {
createShipmentAndOrder(input: $input) {
shipment {
id
orders {
items {
lpn
}
}
}
}
}

Variables:

{
"input": {
"shipment": {
"businessSlug": "your-business",
"facilitySlug": "your-facility",
"shipmentNumber": "SHIP-001",
"direction": "RECEIVING",
"status": "SCHEDULED",
"expectedArrivalAt": "2025-12-16T20:50:47.366Z"
},
"orders": [
{
"orderNumber": "ORD-001",
"direction": "INBOUND",
"expectedQuantity": 3,
"items": [
{ "lpn": "LPN1", "quantityUnit": "PALLET", "quantity": 1 },
{ "lpn": "LPN2", "quantityUnit": "PALLET", "quantity": 1 },
{ "lpn": "LPN3", "quantityUnit": "PALLET", "quantity": 1 }
]
}
]
}
}

Step 3: Receive Pallet Webhooks

As each pallet passes through the Kargo vision system, Kargo pushes a webhook to your endpoint. For the order above with three LPNs, you'll receive three webhooks:

Webhook 1: LPN1

{
"businessSlug": "your-business",
"facilitySlug": "your-facility",
"kargoShipmentId": "1562067",
"kargoPalletId": "121159700",
"occurredAt": "2025-12-16T14:30:00.000Z",
"url": "https://athena.mykargo.com/shipments/1562067/media?pallet=121159700",
"direction": "UNLOADING",
"orders": ["ORD-001"],
"dockId": "1",
"LPN": "LPN1"
}

Webhook 2: LPN2

{
"businessSlug": "your-business",
"facilitySlug": "your-facility",
"kargoShipmentId": "1562067",
"kargoPalletId": "121159701",
"occurredAt": "2025-12-16T14:32:15.000Z",
"url": "https://athena.mykargo.com/shipments/1562067/media?pallet=121159701",
"direction": "UNLOADING",
"orders": ["ORD-001"],
"dockId": "1",
"LPN": "LPN2"
}

Webhook 3: LPN3

{
"businessSlug": "your-business",
"facilitySlug": "your-facility",
"kargoShipmentId": "1562067",
"kargoPalletId": "121159702",
"occurredAt": "2025-12-16T14:35:45.000Z",
"url": "https://athena.mykargo.com/shipments/1562067/media?pallet=121159702",
"direction": "UNLOADING",
"orders": ["ORD-001"],
"dockId": "1",
"LPN": "LPN3"
}

See the Pallet Level Push documentation for full webhook payload details.


Validation Logic

The validation is simple: check if the LPN in the webhook matches one of the lpn values you submitted in the order.

def handle_pallet_webhook(webhook_payload: dict, expected_lpns: list):
"""Handle an incoming pallet webhook from Kargo."""
lpn = webhook_payload.get("LPN")

if lpn in expected_lpns:
print(f"✓ LPN {lpn} matches expected item")
# Add your business logic here
else:
print(f"✗ LPN {lpn} not found in expected items")