WMS Current Inventory
The WMS Current Inventory API receives inventory snapshots from Warehouse Management Systems. It is the ground-truth source for current inventory positions per product, facility and batch, and it feeds the projected on-hand figures used across Inventory Visibility.
Submissions are accepted asynchronously: the API acknowledges receipt and returns a request_id, then validates and processes the payload downstream.
A 202 confirms receipt, not validity. Every rule below is applied after the response is returned. Positions that fail are recorded in FourKites service logs only — no error reaches the caller, and there is no callback today. To confirm a snapshot landed, read it back through the inventory projection APIs.
One bad position no longer discards the rest. Each position is validated on its own. Valid positions in the same message persist even when a sibling is rejected.
Breaking change — the Available category is now OnHand.
Available is no longer accepted. A payload containing it fails to parse, and parsing happens before per-position validation, so the entire message is discarded — every position in it, not just the one at fault. You still receive 202 and no error.
Valid categories are OnHand, QualityHold, Reserved, Blocked and InTransit. Matching is case-insensitive (onhand is accepted); any other value rejects the whole message.
If your integration sends Available today, change it to OnHand.
Validation Rules
Per position — rejects that position only:
- productId, facilityId and batchNumber must be present and non-blank
- categoryBreakdown must be present and non-empty, with at most one entry per category
- every category must be one of the five valid values
- every quantity must be present and ≥ 0
- unitCost and totalValue, when present, must be ≥ 0
- currency, when present, must be exactly 3 characters
- every field must be within its maximum length (see Body Parameters)
Message level — rejects the whole message:
- inventory must be present and non-empty
- at most 500 inventory positions per request
- the body must be parseable JSON
- every category value must be recognised
- lastUpdatedDate, manufacturingDate and expiryDate must be in a parseable format
NA and N/A are treated as "not supplied" for uom and currency, after surrounding whitespace is stripped. Omitting the field and sending a placeholder behave identically.
Data Limits
Limit | Value |
|---|---|
Inventory positions per request | 500 |
categoryBreakdown entries per position | One per category — five categories are defined |
referenceAttributes | No enforced limit on count or size |
Split larger snapshots across multiple requests.
curl --location 'https://api.fourkites.com/api/v1/async/inventory/current?message_id=MSG-CHI-2026-08-14-001' \
--header 'Content-Type: application/json' \
--header 'apikey: APIKEY' \
--data '{
"messageId": "MSG-CHI-2026-08-14-001",
"inventory": [
{
"productId": "SKU-12345",
"facilityId": "FAC-CHI-Z6",
"productName": "Dell Laptop XPS 15",
"productCategory": "Electronics",
"facilityName": "Chicago Warehouse",
"facilityType": "Warehouse",
"batchNumber": "1919149957",
"lotNumber": "BEDU-2423",
"locationType": "STANDARD",
"categoryBreakdown": [
{
"category": "OnHand",
"quantity": 1500
},
{
"category": "QualityHold",
"quantity": 500
},
{
"category": "Reserved",
"quantity": 398
}
],
"uom": "CSE",
"lastUpdatedDate": "2026-08-14T10:30:00Z",
"manufacturingDate": "2026-04-04",
"expiryDate": "2027-10-04",
"materialType": "FINISHED_GOODS",
"unitCost": 45.50,
"currency": "USD",
"totalValue": 109109.00,
"referenceAttributes": {
"warehouseSection": "NORTH-A",
"temperatureZone": "AMBIENT",
"customerId": "CUST-789",
"palletId": "PAL-123456"
}
}
]
}'Projected on-hand for this position is 1500 — the OnHand quantity only.
import http.client
import json
conn = http.client.HTTPSConnection("api-staging.fourkites.com")
payload = json.dumps({
"messageId": "MSG-TEST-001",
"inventory": [
{
"productId": "SKU-12345",
"facilityId": "FAC-CHI-Z6",
"productName": "Dell Laptop XPS 15",
"productCategory": "Electronics",
"facilityName": "Chicago Warehouse",
"facilityType": "Warehouse",
"batchNumber": "1919149957",
"lotNumber": "BEDU-2423",
"locationType": "STANDARD",
"categoryBreakdown": [
{
"category": "OnHand",
"quantity": 1500
},
{
"category": "QualityHold",
"quantity": 500
},
{
"category": "Reserved",
"quantity": 398
}
],
"uom": "CSE",
"lastUpdatedDate": "2026-08-14T10:30:00Z",
"manufacturingDate": "2026-04-04",
"expiryDate": "2027-10-04",
"materialType": "FINISHED_GOODS",
"unitCost": 45.5,
"currency": "USD",
"totalValue": 109109,
"referenceAttributes": {
"warehouseSection": "NORTH-A",
"temperatureZone": "AMBIENT",
"customerId": "CUST-789",
"palletId": "PAL-123456"
}
}
]
})
headers = {
'Content-Type': 'application/json',
'apikey': 'STAGING_APIKEY'
}
conn.request("POST", "/api/v1/async/inventory/current?message_id=MSG-TEST-001", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
Staging requires its own API key. A production key returns 401 against staging. Request a staging key from your FourKites contact before testing here.
Request and body parameters are identical to Production.
Query Parameters
Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
message_id | String | Optional | generated | Correlation id returned to you as request_id — the value to log and to quote in support requests. When omitted, a request_id is generated as evt_current_inventory_<timestamp>. |
company_id | String | Optional | from API key | Resolved from the API key when omitted. Most callers should omit it. |
Response
202 Accepted
{
"request_id": "MSG-CHI-2026-08-14-001"
}request_id echoes message_id when supplied, otherwise a generated id. Use it to correlate with FourKites service logs.
202 means the payload was received and queued. It does not mean the payload was valid, that any position was stored, or that projections were updated. Processing completes asynchronously, typically within a few seconds. A malformed body also returns 202.
401 Unauthorized
{
"message": "Invalid authentication credentials"
}Returned for a missing or invalid apikey.
There are no error codes
Because validation runs after the response, no validation outcome is reported back. There is no error taxonomy to code against, no error callback, no dead-letter feed and no status endpoint. If a snapshot does not appear as expected, raise it with your FourKites contact quoting the request_id.
Repeat sends
The upsert grain is:
(company_id, facility_id, product_id, batch_number)
Re-sending a position with the same four values overwrites the stored quantities rather than adding to them, so re-sending a full snapshot is safe.
This is why batchNumber is mandatory: without it the key is incomplete and repeat sends accumulate as separate positions instead of replacing one another, inflating reported inventory.
How quantities reach projections
Only the OnHand category contributes to projected on-hand inventory.
QualityHold, Reserved, Blocked and InTransit are stored against the snapshot and returned by inventory queries, but are excluded from projections and from stock-risk calculations.
