Air Cargo OS Guide

AWB tracking, ground handling, arrival notices, and cargo customer portals.

Chapter 1 — What Air Cargo OS Gives You

Air Cargo OS adds AWB tracking, ground handling workflows, and air-cargo-specific billing.

What it adds

ModuleWhat it does
M24AWB operations — creation, status sync (pull + push), event timeline.
M12 (air flavour)Air-side receiving.
M17 (air flavour)Air-side fulfillment.
M30 (air flavour)Air-cargo-specific storage rules.
Ground-ops dashboardsPre-alert + AWB queue + ops console.

Default landing path

/console/business/ground-ops/pre-alert

Chapter 2 — Roles That Light Up

RoleWhat they do in Air Cargo OS
company_adminConfigures provider env vars, AWB master data, ground-handling procedures, per-operation storage rules.
operations_managerRuns the ground-ops queue: pre-alerts, receiving, AWB status checks, per-day storage charges.
customer_serviceReads AWB and shipment status; answers customer questions; sees storage warnings.
accountingReads AWB aging and per-operation billing detail.
customer_aircargo (portal)The air-cargo customer portal role. Looks up their AWBs and status. Meaningless without Air Cargo OS.

Chapter 3 — Configuring an AWB Provider

Trenvar reaches your air carrier through environment variables — there's no UI for this. Your platform admin (Trenvar's employee) sets them up once. This chapter walks through both modes.

Mode comparison

ModeUse it when
mockYou're testing or you don't have a live carrier API yet. Trenvar generates deterministic mock statuses.
http_jsonYou have a live carrier with an HTTP API. Trenvar calls it on demand.

Walkthrough — set up the provider in mock mode (testing)

Prerequisites

  • Access to your tenant's deployment environment (you or a Trenvar platform admin).
  • The hosting provider's env-var dashboard or shell access to apps/web/.env.local.

Step-by-step

  1. Open the env-var dashboard (Vercel / Render / your host) or SSH to the deployment.
  2. Set the following env vars:
    AIR_AWB_PROVIDER=mock
    AIR_AWB_PROVIDER_NAME=mock_provider
  3. Save / deploy.
  4. Restart the server (most hosts auto-restart on env change).
  5. Open /console/business/ground-ops/awb-check.
  6. Type any test AWB number (e.g., "TEST-12345678"). Click Check.
  7. Mock mode returns a deterministic status (e.g., "in_transit") with a synthetic event timeline. Use this to validate the UI without a real carrier.

Walkthrough — set up the provider in http_json mode (production)

Prerequisites

  • Carrier has given you: API base URL, path template, an API key, and the auth header name they expect.
  • The carrier supports the JSON payload format Trenvar expects (or you've written an adapter — see Air Cargo Integration doc).

Step-by-step

  1. Set env vars:
    AIR_AWB_PROVIDER=http_json
    AIR_AWB_PROVIDER_NAME=cargo_provider_x
    AIR_AWB_API_BASE_URL=https://api.cargo-provider-x.com
    AIR_AWB_API_PATH_TEMPLATE=/v1/track/{awb}
    AIR_AWB_API_KEY=sk_live_abcd1234ef
    AIR_AWB_API_AUTH_HEADER=x-api-key
    AIR_AWB_WEBHOOK_SECRET=whsec_random_64char_string
  2. Save / deploy / restart.
  3. Open /console/business/ground-ops/awb-check.
  4. Type a real AWB number that you know exists at the carrier. Click Check.
  5. Trenvar calls GET https://api.cargo-provider-x.com/v1/track/{awb} with header x-api-key: sk_live_abcd1234ef.
  6. Verify the returned status, origin, destination, and event timeline match what the carrier shows.
Restart required
Env-var changes require a server restart. Until restart, Trenvar uses the old config — including the old API key. Time changes when traffic is low.

Chapter 4 — Walkthrough: Check an AWB (Pull Mode)

"Pull" means a user clicks Check and Trenvar fetches status from the carrier on demand. This is the most common operator workflow.

Where
/console/business/ground-ops/awb-check

Walkthrough — operator looks up an AWB

Prerequisites

  • operations_manager or company_admin (or any role with wms.shipments.read).
  • AWB provider configured (Chapter 3).

What the screen looks like

Header: "AWB Lookup". Top of the page: a large input field labelled "AWB Number" with placeholder "e.g., 123-12345678". Below: a Check button. Below that: an empty result panel.

Step-by-step

  1. Type or paste the AWB number. Trenvar accepts spaces and dashes — it normalizes "CX 1234 5678 90" to "CX1234567890" automatically.
  2. Click Check / Create.
  3. Spinner: "Querying carrier..."
  4. Within 5–15 seconds, the result panel populates with:
    • AWB number (normalized).
    • Status pill (in_transit / arrived / delivered / etc., colored).
    • Origin → Destination with airport codes.
    • Flight number (latest known).
    • Event timeline — newest event at top: status + location + timestamp + free-text details.
    • Last synced timestamp.
  5. If the data is fresh (under 15 minutes old in cache), Trenvar returns the cached version instantly without re-calling the carrier. Look at "Last synced" to check.
  6. Click Force Refresh if you suspect stale data; this bypasses the cache.

Worked example

Customer calls asking "where's my shipment?" with AWB "160 12345678".

  1. Open /console/business/ground-ops/awb-check.
  2. Type "160 12345678". Trenvar normalizes to "16012345678".
  3. Click Check. After 8 seconds: status = "arrived", origin = HKG, destination = YVR, flight = CX838, last event "Arrived at YVR cargo terminal" at 14:22.
  4. Tell the customer: "Your shipment arrived at Vancouver this afternoon. We'll pick it up tomorrow."

What happens behind the scenes

  • AWB record stored at tenants/{tenantId}/awb/{awbDocId}.
  • Events stored under .../awb/{awbDocId}/events/.
  • Cache TTL: 15 minutes. Older = re-fetch.
  • Audit log records the lookup with actor + AWB + timestamp.

Chapter 5 — Walkthrough: Webhook Ingestion (Push Mode)

"Push" means the carrier POSTs status updates to Trenvar in real time. No polling needed. Set this up once with the carrier's IT team.

Endpoint to give the carrier

POST www.trenvar.com/your-tenant/api/integrations/air-cargo/webhook

Walkthrough — give the carrier credentials

Step-by-step

  1. Generate a strong random secret (your platform admin can do this — typical format whsec_ + 64 hex chars).
  2. Set AIR_AWB_WEBHOOK_SECRET env var to that value. Restart server.
  3. Send the carrier:
    • The endpoint URL.
    • The shared secret.
    • Which header to send it in (either Authorization: Bearer {SECRET} or x-air-awb-webhook-secret: {SECRET}).
    • The expected JSON payload format (see below).
    • An optional x-air-awb-event-id header for idempotency (deduplication if they retry).
  4. The carrier's IT team configures their outbound integration. They send a test event.
  5. Watch the audit log at /console/owner/audit (or tenant audit log) for entries with actor_uid="air_awb_webhook". The first one confirms the integration is live.

Expected payload

{
  "tenantId": "tenant_acme",
  "provider": "cargo_provider_x",
  "awbNumber": "123-12345678",
  "status": "in_transit",
  "flightNo": "CX838",
  "origin": "HKG",
  "destination": "YVR",
  "events": [
    {
      "status": "in_transit",
      "eventAt": "2026-03-13T09:35:00Z",
      "location": "HKG",
      "details": "Departed origin station"
    }
  ]
}

What Trenvar does on each webhook

  1. Validates the secret header (rejects with 401 if wrong).
  2. Normalizes the AWB number.
  3. Upserts the AWB record.
  4. Appends new events (skips duplicates if event-id matches existing).
  5. Writes an audit entry with actor_uid="air_awb_webhook", actor_role="system_webhook".
  6. Returns 200 OK.
If carrier webhooks aren't arriving
Common causes: wrong endpoint URL, wrong secret, JSON schema mismatch. Check audit log for 401s. Coordinate with the carrier's IT team. As a fallback, pull mode (Chapter 4) keeps you running while you debug.

Payload

{
  "tenantId": "tenant_acme",
  "provider": "cargo_provider_x",
  "awbNumber": "123-12345678",
  "status": "in_transit",
  "flightNo": "CX838",
  "origin": "HKG",
  "destination": "YVR",
  "events": [
    {
      "status": "in_transit",
      "eventAt": "2026-03-13T09:35:00Z",
      "location": "HKG",
      "details": "Departed origin station"
    }
  ]
}

Trenvar validates the secret, normalizes the AWB number, upserts the record, appends events, and writes an audit entry tagged with actor_uid="air_awb_webhook" and actor_role="system_webhook".

Chapter 6 — AWB Status Lifecycle

StatusDisplayTerminal?
createdCreatedNo
bookedBookedNo
receivedReceivedNo
in_transitIn TransitNo
arrivedArrivedNo
available_for_pickupAvailable for PickupNo
deliveredDeliveredYes
cancelledCancelledYes
exceptionExceptionNo
unknownUnknownNo

Aliases

Trenvar normalizes provider-specific status names: "transit"/"departed"/"en_route" → in_transit; "ready_for_pickup" → available_for_pickup; "canceled" → cancelled; "failed"/"hold"/"on_hold"/"customs_hold"/"returned" → exception.

Chapter 7 — Linking AWBs to Pre-Alerts & Shipments

An AWB on its own is just tracking. It becomes operationally meaningful when linked to a pre-alert (inbound) or shipment (outbound). This chapter walks through both link types.

Walkthrough A — link AWB to inbound pre-alert

Use case

Customer sends you an AWB. You're expecting the cargo at your warehouse. You create a pre-alert and link the AWB so receiving can see both sides of the picture.

Step-by-step

  1. First, look up the AWB at /console/business/ground-ops/awb-check (Chapter 4). This creates the AWB record if it doesn't exist.
  2. Go to /console/ops-manager/pre-alert. Click Create Pre-Alert.
  3. Fill the pre-alert as usual (Warehouse OS Chapter 5).
  4. In the Source dropdown, pick air_cargo.
  5. A new field appears: AWB Reference. Typeahead on existing AWBs in the system. Pick the AWB you just looked up.
  6. Save the pre-alert. Trenvar now sets linked_prealert_id on the AWB record (back-link) and awb_reference on the pre-alert (forward-link).

What you gain

  • The pre-alert detail screen shows the AWB's live status next to the expected lines.
  • The AWB detail screen shows the linked pre-alert and its receiving status.
  • The customer (with customer_aircargo) can see the AWB in their portal.
  • Audit trail across both records is unified.

Walkthrough B — link AWB to outbound shipment

Use case

You're shipping cargo out by air. You've created a shipment in Warehouse OS; the carrier issues an AWB; you link them.

Step-by-step

  1. Create the outbound shipment as normal.
  2. Once the carrier returns an AWB number, look it up at /console/business/ground-ops/awb-check.
  3. From the AWB detail panel, click Link to Shipment.
  4. Modal: typeahead. Pick the outbound shipment.
  5. Save. linked_shipment_ref on the AWB and awb_reference on the shipment are both set.

Walkthrough C — link AWB to customer for portal visibility

  1. Open the AWB detail at /console/business/ground-ops/awb-check.
  2. Click Link to Customer.
  3. Pick the customer. Save.
  4. The customer can now see the AWB in their portal (if they have the customer_aircargo role).
Without these links, the AWB is "orphan"
An unlinked AWB is visible in the operator's AWB-check screen but not surfaced anywhere else — not on pre-alerts, not on shipments, not in customer portals. Always link.

Chapter 8 — Walkthrough: Customer Looks Up Their Own AWB

Customers with the customer_aircargo role can look up AWBs from the portal — but only ones linked to their own pre-alerts or shipments.

Walkthrough — admin invites a customer_aircargo user

  1. You (company_admin) go to /console/business/settings/users.
  2. Add User. Email = customer's email. Role = customer_aircargo. Linked Customer = their customer record.
  3. Save & invite. Customer accepts, sets password.

Walkthrough — customer looks up an AWB

  1. Customer signs in to the portal.
  2. Lands on their portal home (typically /console/customer/awb-lookup for customer_aircargo).
  3. Sees a single screen: AWB number input + Look Up button.
  4. Customer types their AWB number, clicks Look Up.
  5. Trenvar checks: is this AWB linked to one of this customer's pre-alerts/shipments?
    • If yes → status, origin/destination, flight, event timeline shown.
    • If no → "AWB not found in your account. Contact your account manager if this is unexpected."
Cross-customer isolation
Customers cannot see AWBs not linked to their pre-alerts/shipments. Even if they happen to know another customer's AWB number, the system rejects the lookup. This is enforced server-side, not just hidden in UI.

Chapter 9 — Air-Cargo-Specific Storage Billing

Air Cargo OS unlocks the storage billing screens (same ones 3PL OS unlocks). The model is now free-form: you define your own Unit Codes (CBM, PALLET, BARREL, LITRE, etc.), set a Quantity Source per rule, and assign SKUs to the matching Unit Code in Item Master.

Where
/console/business/storage/rules  ·  /console/business/storage/accrual  ·  /console/business/storage/aging

The three-layer model (recap)

  1. Storage Rule defines the contract: Unit Code, Quantity Source, cadence, price.
  2. Unit Code is the key linking the rule to SKUs (case-sensitive string match).
  3. Item Master / Customer Catalog tells the engine which Unit Code each SKU uses.

Quantity Source options (air cargo most common)

Quantity SourceEngine measuresAir-cargo fit
Volume (CBM)Cubic metresMost common — most cargo contracts are CBM.
PalletsPallet-typed HUsFor ULD-aware ops or pallet rental.
Assigned SKU Storage UnitsSKU's Storage Billing Qty/Unit × stocked unitsFor freight-forwarder contracts using non-standard units like DRUM, CRATE, ULD.
Handling UnitsHU countWhen each carton tracked individually.
Occupied BinsBins in useLess common in air cargo.
Flat RentalFixed per periodPrepaid cargo or simple retainer.

Walkthrough A — create a CBM rule for air cargo

  1. Go to /console/business/storage/rulesCreate Rule.
  2. Fill:
    • Code → "AC-CBM-DAILY".
    • Name → "Air Cargo CBM Storage".
    • Unit CodeCBM.
    • Unit Label → "CBM".
    • Quantity Source → Volume (CBM).
    • Cadence → Daily.
    • Unit Price → 1.50.
    • Free Days → 3 (typical air cargo grace).
    • Customer Scope → blank or specific cargo customer.
  3. Save.
  4. In Item Master, set Storage Billing Unit Code = CBM on every cargo SKU (or use Customer Catalog override per client).

Walkthrough B — free-form unit for an unusual contract (e.g., DRUM)

One forwarder bills by drum count regardless of volume.

  1. Create Rule. Unit Code = DRUM. Unit Label = "Drum". Quantity Source = Assigned SKU Storage Units. Cadence = Monthly. Unit Price = 35.00. Customer Scope = that forwarder.
  2. In Item Master for that forwarder's SKUs (or via Customer Catalog override): Storage Billing Unit Code = DRUM, Storage Billing Qty/Unit = 1.
  3. Save. The forwarder's storage billing now uses drum count.

Resolution priority (5 layers)

PrioritySource
1 (highest)Inventory row's storage_rule_id / storage_rule_code (rare overrides only)
2Customer Catalog storage assignment (per-client SKU override; reached via WMS → Item Master → 3PL context → Edit Rules; Unit Code is a dropdown of active rules — create the rule first)
3Client General Storage Billing Rule (set on Customers → [client] → General Storage Billing Rule; client-level fallback when the whole client is mostly billed one way)
4Item Master storage assignment (tenant-wide default for the SKU)
5 (lowest)Auto-match / default tenant rule (implicit fallback)
For air cargo customers
Most cargo clients are billed mostly by CBM. Setting their General Storage Billing Rule to a CBM rule on the customer record covers 90% of cases without per-SKU configuration. Use Item Master / Customer Catalog only for SKUs that bill differently (e.g., a forwarder who wants drums or pallets for specific products).

Data quality requirements

  • Volume (CBM) — inventory rows carry volume_cm3, or Item Master / Customer Catalog have dimensions for CBM resolution.
  • Assigned SKU Storage Units — SKU has Storage Billing Unit Code matching the rule, plus Storage Billing Qty/Unit if billed quantity should derive from the SKU.
  • Pallets / Handling Units — HU types accurate.
  • Occupied Bins — operators put away to real bins.
  • All sources — inventory ownership tagged to the correct cargo customer.

For full walkthroughs covering creating rules, customer-scoped overrides, monthly accrual, and the vape-3PL mixed-unit example, see 3PL OS Chapter 5 — the mechanics are identical, only the operational context (air cargo vs. consumer goods) differs.

Chapter 10 — Daily Flow per Role

Operations manager's day

  1. Open ground-ops pre-alert queue.
  2. For each inbound AWB: create pre-alert → check AWB status → set up receiving when goods land.
  3. Monitor exceptions (customs hold, damage, missing pieces).
  4. Watch storage aging on slow-moving cargo.

Customer service's day

  1. Look up AWB status in response to customer questions.
  2. Open cases for delivery exceptions.

Customer (customer_aircargo) day

  1. Log in to portal.
  2. Look up AWB status.
  3. View invoices, pay if due.

Appendix A — Air Cargo OS Console Paths

PathScreen
/console/business/ground-ops/pre-alertGround-ops pre-alert queue
/console/business/ground-ops/awb-checkAWB lookup / create
/console/business/ground-ops/receivingAir-side receiving
/console/business/storage/rulesStorage rules
/console/business/storage/accrualStorage accrual
/console/business/storage/agingStorage aging
/console/business/billing/servicesService catalog
/console/business/billing/pricing-rulesPricing rules
/console/business/billing/invoicesInvoices
/console/business/billing/taxTax
(customer portal AWB lookup — exact path is tenant-customizable)Customer-facing AWB status

Appendix B — Air Cargo OS Permissions & Environment

Permissions

PermissionHeld by
wms.shipments.readoperations_manager, customer_service, accounting
dispatch.tracking.readoperations_manager, customer_service, accounting (for AWB visibility)
storage.accrual.read, storage.rules.readoperations_manager, accounting
customer.orders.viewcustomer_aircargo (gates AWB lookup)
customer.invoices.view, customer.payments.paycustomer_aircargo

Required entitlement

  • platform_os.air_cargo_os.enabled = true on the tenant.
  • OR addons.ground_ops.enabled = true (legacy alias).

Appendix C — Glossary

Every Air-Cargo-OS-specific term, in plain English.

AWB (Air Waybill) — The carrier's tracking number for an air cargo shipment. Format like 123-12345678.

AWB record — The Trenvar-side record of an AWB with its status, origin, destination, flight, and event timeline. Cached for 15 minutes.

Cache TTL — How long Trenvar reuses a previously-fetched AWB status before re-calling the carrier. 15 minutes by default.

Carrier provider — The airline or air-cargo provider (e.g., cargo_provider_x). Configured by environment variable.

Customs hold — A common cause of "Exception" status. Cargo can't move until paperwork or duties are cleared.

Force Refresh — Bypasses the 15-minute cache and re-fetches AWB status from the carrier in real time.

Ground handler — Local company that picks up cargo from the airline at the destination airport.

HTTP JSON mode — Production AWB provider mode where Trenvar calls a real carrier API to fetch status.

Idempotency header — Optional x-air-awb-event-id header on webhooks. Lets Trenvar deduplicate retried events from the carrier.

Linked pre-alert — An inbound pre-alert tied to an AWB (via linked_prealert_id). Connects carrier tracking to warehouse receiving.

Linked shipment — An outbound shipment tied to an AWB (via linked_shipment_ref).

Mock mode — Test AWB provider mode that generates fake-but-deterministic statuses. Useful for validating the UI without a live carrier.

Origin / Destination — Three-letter IATA airport codes (HKG = Hong Kong, YVR = Vancouver, JFK = New York, LHR = London Heathrow).

Pull mode — Trenvar fetches AWB status on demand when a user clicks Look Up.

Push mode — Carrier sends AWB status updates to Trenvar via webhook in real time. Faster than pull mode but requires carrier-side integration.

Status pill — Coloured badge showing the AWB's current status (Booked, In Transit, Arrived, Delivered, Exception, etc.).

Webhook secret — Shared secret string the carrier uses to authenticate when sending push events. Set as AIR_AWB_WEBHOOK_SECRET env var.

Trenvar Support
Email info@trenvar.com  ·  www.trenvar.com

End of Air Cargo OS Guide  ·  v1.0  ·  May 2026