Logiveo Aggregator API
Rate-shop three LTL carriers simultaneously and book pickups — all through a unified API. Returns normalized, ShipEngine-style quotes. Carrier credentials are stored server-side — your request body contains only the shipment or pickup details.
How it works — Rate shop
How it works — Pickup / Booking
Carriers
| Carrier | Auth method | Protocol | Actions |
|---|---|---|---|
| FedEx Freight LTL | OAuth2 client_credentials | REST / JSON | RATE, SHIP, PICKUP_* |
| Daylight LTL | OAuth2 + credentials in body | REST / JSON | RATE_QUOTE, PICKUP |
| BTX Air / LTL | CustomerID in SOAP body | SOAP / XML | RATE, BOOKING |
Authentication
All endpoints except GET /api/health require an X-Api-Key header. Keys are prefixed with lgv_sk_ and stored server-side.
X-Api-Key: lgv_sk_your_api_key_here
Test API Key
A shared sandbox key is available for development and testing:
lgv_sk_08f018cb6acc7c8e5e28ead6d9f3d215
Customer Onboarding
Self-service API key provisioning is coming soon. When available, new customers will be able to register, receive a dedicated key, and configure their own carrier credentials.
In the meantime, contact the administrator to request a production API key with your own carrier accounts.
Error responses
| Status | Condition | Body |
|---|---|---|
| 401 | Missing or invalid API key | {"error": "Missing X-Api-Key header."} |
| 401 | Key revoked or inactive | {"error": "Invalid or revoked API key."} |
GET /api/health
Returns server status and the list of registered carriers. Use this to verify the API is up before making rate requests.
Response
{
"status": "ok",
"carriers": [
"FedEx Freight LTL",
"Daylight LTL",
"BTX_AIR"
]
}
Example
curl https://logiveoaggregator.vercel.app/api/health
GET /api/carriers
Returns metadata for all registered carriers: supported actions and the credential schema they accept (for reference — credentials are configured server-side).
Example
curl https://logiveoaggregator.vercel.app/api/carriers \
-H "X-Api-Key: lgv_sk_your_key"
Response
[
{
"id": "FedEx Freight LTL",
"label": "FedEx Freight LTL",
"actions": ["RATE", "SHIP", "PICKUP_AVAILABILITY", "PICKUP_CREATE", "PICKUP_CANCEL", "SCHEDULE_PICKUP"],
"credentialsSchema": [
{ "key": "clientId", "label": "Client ID", "required": true, "secret": false },
{ "key": "clientSecret", "label": "Client Secret", "required": true, "secret": true },
{ "key": "accountNumber", "label": "Account Number", "required": true, "secret": false },
{ "key": "baseUrl", "label": "Base URL", "required": false, "secret": false }
]
},
{
"id": "Daylight LTL",
"label": "Daylight LTL",
"actions": ["RATE_QUOTE", "PICKUP"],
"credentialsSchema": [
{ "key": "key", "label": "Client Key", "required": true, "secret": false },
{ "key": "secret", "label": "Client Secret", "required": true, "secret": true },
{ "key": "accountNumber", "label": "Account Number", "required": true, "secret": false },
{ "key": "userName", "label": "Username", "required": true, "secret": false },
{ "key": "password", "label": "Password", "required": true, "secret": true }
]
},
{
"id": "BTX_AIR",
"label": "BTX_AIR",
"actions": ["RATE", "BOOKING"],
"credentialsSchema": [
{ "key": "customerId", "label": "Customer ID (GUID)", "required": true, "secret": false }
]
}
]
POST /api/rates
Rate-shops all three carriers simultaneously. Returns normalized quotes from each carrier in a single response. Carrier credentials are loaded from server environment — you only provide the shipment.
Shipment schema
| Field | Type | Required | Description |
|---|---|---|---|
| shipment.origin | object | Required | Pickup location (see address fields below) |
| shipment.destination | object | Required | Delivery location |
| shipment.items[] | array | Required | Freight line items (see item fields below) |
| shipment.shipDate | string | Required | Pickup date in YYYY-MM-DD format |
| shipment.accessorials | array | Optional | Accessorial service codes (e.g. "LIFTGATE_PICKUP") |
| shipment.cod | number | Optional | COD amount in USD (default: 0) |
| shipment.declaredValue | number | Optional | Declared value in USD (default: 0) |
| shipment.insuranceValue | number | Optional | Insurance value in USD (default: 0) |
Address fields (origin / destination)
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Optional | Company or person name |
| address1 | string | Required | Street address line 1 |
| address2 | string | Optional | Suite, unit, etc. |
| city | string | Required | City |
| state | string | Required | 2-letter state code (e.g. CA) |
| postalCode | string | Required | ZIP code |
| country | string | Optional | Country code (default: US) |
| phone | string | Optional | Phone number (digits only) |
| contact | string | Optional | Contact person name |
Item fields (items[])
| Field | Type | Required | Description |
|---|---|---|---|
| weight | number | Required | Weight in pounds |
| freightClass | string | Required | NMFC freight class: 50, 55, 60, 65, 70, 77.5, 85, 92.5, 100, 110, 125, 150, 175, 200, 250, 300, 400, 500 |
| pieces | number | Required | Number of handling units |
| description | string | Optional | Commodity description |
| length | number | Optional | Length in inches |
| width | number | Optional | Width in inches |
| height | number | Optional | Height in inches |
| nmfcNumber | string | Optional | NMFC item number |
| hazmat | boolean | Optional | Hazardous material flag (default: false) |
Example request
curl -X POST https://logiveoaggregator.vercel.app/api/rates \
-H "Content-Type: application/json" \
-H "X-Api-Key: lgv_sk_your_key" \
-d '{
"shipment": {
"origin": {
"name": "Test Shipper Co",
"address1": "1202 Chalet Ln",
"city": "Harrison",
"state": "AR",
"postalCode": "72601",
"country": "US",
"phone": "8705550100",
"contact": "Shipping Dept"
},
"destination": {
"name": "Widget Company",
"address1": "525 S Winchester Blvd",
"city": "San Jose",
"state": "CA",
"postalCode": "95128",
"country": "US",
"phone": "4085550100",
"contact": "Receiving Dept"
},
"items": [
{
"description": "Industrial Equipment",
"weight": 500,
"length": 48,
"width": 40,
"height": 48,
"pieces": 1,
"freightClass": "70"
}
],
"shipDate": "2026-03-03"
}
}'
Response shape
The response envelope wraps all carrier results. Each carrier entry has the same structure regardless of success or failure.
| Field | Type | Description |
|---|---|---|
| durationMs | number | Total wall-clock time for all carrier calls |
| carriers | object | Map of carrierId → carrier result |
| carriers[id].status | number | HTTP status from the carrier API (200 = success) |
| carriers[id].error | string|null | Error message if any step failed, otherwise null |
| carriers[id].durationMs | number | Time for this carrier's calls (auth + API) |
| carriers[id].auditLog | array | Ordered steps: auth then action, each with step, name, success, durationMs, message |
| quotes | array | Flat array of all quotes across all carriers (top-level, same level as carriers). FedEx contributes multiple items (one per service type); Daylight and BTX contribute one each. |
quotes[] — ShipEngine quote object
Each quote in the top-level quotes array includes a carrier descriptor so you know which carrier produced it, then the standard ShipEngine fields.
| Field | Type | Availability | Description |
|---|---|---|---|
| carrier_message | null | ❌ none | Carrier message — not returned by any carrier API currently |
| carrier_quote_id | string|null | FedEx ✅ Daylight ✅ BTX ❌ | Carrier-issued quote reference number |
| charges[] | array | All ✅ | Itemized charges (see charge types below) |
| effective_date | null | ❌ none | Rate effective date — not returned by any carrier |
| estimated_delivery_days | number|null | FedEx ✅ Daylight ❌ BTX ✅ | Transit days estimate (FedEx: returnTransitTimes enabled, with deliveryDate fallback) |
| expiration_date | null | ❌ none | Quote expiration — not returned by any carrier |
| pickup_date | string|null | FedEx ✅ Daylight ✅ BTX ✅ | Earliest pickup date. FedEx: PICKUP_AVAILABILITY API. Daylight: from response. BTX: shipDate. |
| quote_id | string|null | ✅ all | Aggregator-generated ID (AGG-XXXXX). Stored in KV with 24h TTL. Use for pickup scheduling. |
| quote_type | null | ❌ none | Quote type — not returned by any carrier |
| service.carrier_description | string|null | All ✅ | Human-readable service name |
| service.code | string | All ✅ | Carrier service code (e.g. FEDEX_FREIGHT_ECONOMY) |
| shipment | object|null | All ✅ | Echoed input shipment object |
Charge types
| type | Description |
|---|---|
| container | Base freight charge (line haul) |
| accessorial | Fuel surcharge, liftgate, residential delivery, etc. |
| discount | Account or contract discount |
| total | Net total after all charges and discounts |
POST /api/pickup
Schedule a pickup or create a booking for a single carrier. Supports all 3 carriers: BTX_AIR (BOOKING), Daylight LTL (PICKUP), and FedEx Freight LTL (PICKUP_CREATE). After rate-shopping with /api/rates, pick a quote and submit it here. The API transforms your normalized payload into the carrier-specific format and routes to the selected carrier.
POST /api/rates → user picks a quote → POST /api/pickup with carrierId and quoteId from the selected quote. The quoteId enables automatic KV enrichment.
KV Quote Enrichment
When a quoteId (e.g. AGG-00123) is provided, the API automatically looks up the stored rate quote in KV to enrich the pickup request with data from the original quote. This eliminates the need for callers to pass carrier-specific fields explicitly.
| Carrier | KV Enrichment | Details |
|---|---|---|
| FedEx Freight LTL | serviceType |
Resolves FEDEX_FREIGHT_PRIORITY vs FEDEX_FREIGHT_ECONOMY from the original rate quote, so the correct service is used for the pickup. |
| Daylight LTL | shipmentID |
The quoteId is used as Daylight's required shipmentID. From NetSuite, the carrier_quote_id (Daylight's own quote number) is sent as quoteId so it maps correctly. |
| BTX_AIR | N/A | No KV enrichment needed — booking uses the normalized pickup payload directly. |
quoteId when available. It enables service-type resolution for FedEx and shipmentID mapping for Daylight, ensuring the pickup matches the exact quote the user selected.
Carrier → Action mapping
| carrierId | Action | Auth | HTTP Calls |
|---|---|---|---|
| FedEx Freight LTL | PICKUP_CREATE | OAuth + Bearer | 2 |
| Daylight LTL | PICKUP | OAuth + Bearer | 2 |
| BTX_AIR | BOOKING | None (CustomerID in XML) | 1 |
Pickup schema
| Field | Type | Required | Description |
|---|---|---|---|
| carrierId | string | Required | Carrier ID: FedEx Freight LTL, Daylight LTL, or BTX_AIR |
| quoteId | string | Recommended | Quote ID from /api/rates (e.g. AGG-00123). Enables KV enrichment: resolves FedEx serviceType from the stored quote, and maps to Daylight's shipmentID. From NetSuite, send the carrier_quote_id for Daylight. |
| pickup.pickupDate | string | Required | Pickup date in YYYY-MM-DD format |
| pickup.readyTime | string | Optional | Ready time (e.g. 14:00:00). Default varies by carrier. |
| pickup.closeTime | string | Optional | Close time (e.g. 17:00:00) |
| pickup.origin | object | Required | Pickup location — same address fields as /api/rates |
| pickup.destination | object | Required | Delivery location — same address fields as /api/rates |
| pickup.items[] | array | Required | Freight line items (weight, pieces, description, dimensions) |
| pickup.tzOffset | string | Optional | Timezone offset for FedEx (e.g. -06:00). Default: -06:00 |
| pickup.specialInstructions | string | Optional | Special instructions (Daylight, BTX) |
| pickup.poNumber | string | Optional | PO number (BTX only) |
| pickup.reference1 | string | Optional | Reference number (BTX only) |
FedEx Freight Pickup payload
The pickup mapper transforms your normalized payload into the official FedEx Freight Pickup API schema. Key structure:
freightPickupDetail.lineItems[]— containsservice,destination,packaging,weight,totalHandlingUnitsservice— resolved automatically from KV whenquoteIdis provided (e.g.FEDEX_FREIGHT_PRIORITYorFEDEX_FREIGHT_ECONOMY)payment— a string value"SENDER", not a nested object
Example request — FedEx pickup
curl -X POST https://logiveoaggregator.vercel.app/api/pickup \
-H "Content-Type: application/json" \
-H "X-Api-Key: lgv_sk_your_key" \
-d '{
"carrierId": "FedEx Freight LTL",
"quoteId": "AGG-00098",
"pickup": {
"pickupDate": "2026-03-05",
"readyTime": "14:00:00",
"closeTime": "17:00:00",
"tzOffset": "-06:00",
"origin": {
"name": "Test Shipper Co",
"address1": "1202 Chalet Ln",
"city": "Harrison",
"state": "AR",
"postalCode": "72601",
"country": "US",
"phone": "8705550100",
"contact": "Shipping Dept"
},
"destination": {
"name": "Customer Co",
"address1": "525 S Winchester Blvd",
"city": "San Jose",
"state": "CA",
"postalCode": "95128",
"country": "US",
"phone": "4085550100",
"contact": "Receiving Dept"
},
"items": [{
"description": "Industrial Equipment",
"weight": 500,
"pieces": 1
}]
}
}'
quoteId (AGG-00098) is used to look up the stored rate quote in KV. The serviceType (e.g. FEDEX_FREIGHT_PRIORITY) is resolved automatically — you do not need to pass it in the request body.
Example request — BTX booking
curl -X POST https://logiveoaggregator.vercel.app/api/pickup \
-H "Content-Type: application/json" \
-H "X-Api-Key: lgv_sk_your_key" \
-d '{
"carrierId": "BTX_AIR",
"quoteId": "AGG-00112",
"pickup": {
"pickupDate": "2026-03-05",
"readyTime": "13:00",
"origin": {
"name": "Test Shipper",
"address1": "100 Main St",
"city": "Hillsborough",
"state": "NJ",
"postalCode": "08844",
"country": "US",
"phone": "9085550100",
"contact": "Test Contact",
"openTime": "08:00",
"closeTime": "17:00"
},
"destination": {
"name": "Test Consignee",
"address1": "200 Commerce Dr",
"city": "Bridgeport",
"state": "CT",
"postalCode": "06601",
"country": "US",
"phone": "2035550100",
"contact": "Receiving Dept"
},
"items": [{
"description": "Test Pallet",
"weight": 250,
"length": 48,
"width": 40,
"height": 48,
"pieces": 1
}],
"poNumber": "PO-001",
"reference1": "REF-001"
}
}'
Response shape
The response is normalized across all carriers by the mapPickupResponse() mapper. The top-level shape is: { carrier: { id }, booking: { success, confirmationNumber, errorDescription }, quoteId, auditLog: [] }. The booking object provides a consistent interface for checking success/failure and extracting confirmation numbers, regardless of the carrier. The response field still contains the raw carrier-specific data (JSON for FedEx/Daylight, { xml, json } for BTX).
{
"carrier": { "id": "BTX_AIR" },
"quoteId": "AGG-00112",
"credentialSource": "customer",
"status": 200,
"error": null,
"durationMs": 1712,
"auditLog": [
{ "step": 1, "name": "BTX Auth", "success": true, "durationMs": 0, "message": "No OAuth – CustomerID embedded in request XML" },
{ "step": 2, "name": "BOOKING", "success": true, "durationMs": 1711, "message": "200 OK" }
],
"booking": {
"success": true,
"confirmationNumber": "SDF40006125",
"errorDescription": null
},
"request": { "params": { "customerId": "...", "shipFrom": { "..." : "..." }, "shipTo": { "..." : "..." }, "freightItems": [ "..." ] }, "xml": "..." },
"response": {
"xml": "<?xml ...><BookingResult><Error>false</Error><BookingNumber>SDF40006125</BookingNumber></BookingResult>...",
"json": { "Body": { "BookingResponse": { "BookingResult": { "Error": "false", "ErrorDescription": null, "BookingNumber": "SDF40006125" } } } }
},
"rawResponse": "..."
}
{
"carrier": { "id": "FedEx Freight LTL" },
"quoteId": "AGG-00098",
"credentialSource": "customer",
"status": 200,
"error": null,
"durationMs": 1234,
"auditLog": [
{ "step": 1, "name": "OAuth", "success": true, "durationMs": 450, "message": "Token obtained" },
{ "step": 2, "name": "PICKUP_CREATE", "success": true, "durationMs": 780, "message": "200 OK" }
],
"booking": {
"success": true,
"confirmationNumber": "PCN-12345",
"errorDescription": null
},
"request": { "..." : "..." },
"response": {
"output": { "pickupConfirmationNumber": "PCN-12345" }
},
"rawResponse": "..."
}
{
"carrier": { "id": "BTX_AIR" },
"quoteId": "AGG-00112",
"credentialSource": "customer",
"status": 200,
"error": "BOOKING error (HTTP 200): Invalid pickup date",
"durationMs": 890,
"auditLog": [ "..." ],
"booking": {
"success": false,
"confirmationNumber": null,
"errorDescription": "BOOKING error (HTTP 200): Invalid pickup date"
},
"request": { "..." : "..." },
"response": { "..." : "..." },
"rawResponse": "..."
}
Error responses
| Status | Condition | Body |
|---|---|---|
| 400 | Missing carrierId |
{"error": "Missing required field: carrierId"} |
| 400 | Unknown carrier | {"error": "Unknown or unsupported carrier: ..."} |
| 401 | Missing or invalid API key | {"error": "Missing X-Api-Key header."} |
FedEx Freight LTL
Authentication
OAuth2 client_credentials grant. The adapter exchanges clientId + clientSecret for a Bearer token at POST /oauth/token, then uses it on the rate request. Token lifetime: 3600s.
POST https://apis-sandbox.fedex.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=l759aeaf2b5b3c4...&client_secret=cb9794f089e84...
Rate request
The common shipment is transformed to FedEx's freightRequestedShipment schema and posted to POST /rate/v1/freight/rates/quotes.
Key transformations:
freightClass "70"→"CLASS_070"(FedEx class format)address1→streetLines[]arraystate→stateOrProvinceCode
{
"accountNumber": { "value": "510087020" },
"rateRequestControlParameters": {
"returnTransitTimes": false,
"rateSortOrder": "SERVICENAMETRADITIONAL"
},
"freightRequestedShipment": {
"shipper": {
"address": {
"streetLines": ["1202 Chalet Ln"],
"city": "Harrison",
"stateOrProvinceCode": "AR",
"postalCode": "72601",
"countryCode": "US"
}
},
"recipient": {
"address": {
"streetLines": ["525 S Winchester Blvd"],
"city": "San Jose",
"stateOrProvinceCode": "CA",
"postalCode": "95128",
"countryCode": "US"
}
},
"serviceType": "",
"preferredCurrency": "USD",
"rateRequestType": ["LIST"],
"shipDateStamp": "2026-03-03",
"requestedPackageLineItems": [
{ "weight": { "units": "LB", "value": 500 }, "subPackagingType": "SKID" }
],
"freightShipmentDetail": {
"role": "SHIPPER",
"accountNumber": { "value": "510087020" },
"totalHandlingUnits": 1,
"lineItem": [
{
"id": "1",
"freightClass": "CLASS_070",
"handlingUnits": 1,
"pieces": 1,
"subPackagingType": "SKID",
"weight": { "units": "LB", "value": 500 }
}
]
}
}
}
Audit log (per request)
[
{ "step": 1, "name": "OAuth", "success": true, "durationMs": 559, "message": "Token obtained" },
{ "step": 2, "name": "RATE", "success": true, "durationMs": 4200, "message": "200 OK" }
]
Daylight LTL
Authentication
OAuth2 client_credentials grant using API key and secret. The token URL contains a double-slash — this is required by the Daylight API gateway.
POST https://test-api.dylt.com//oauth/client_credential/accesstoken?grant_type=client_credentials
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(key:secret)
//oauth/... is intentional and required by the Dylt API gateway. Using a single slash will result in a 404.
In addition to the Bearer token, accountNumber, userName, and password are also embedded in every request body.
Rate request
Mapped to the dyltRateQuoteReq JSON schema and posted to POST //rateQuote.
Key transformations:
origin→shipperInfo.customerAddress(usesstreetAddress, notaddress1)items[].freightClass→actualClass(string as-is, no class prefix)items[].pieces→ bothpcsandpallets
{
"dyltRateQuoteReq": {
"accountNumber": "123456",
"userName": "YOUR_USERNAME",
"password": "YOUR_PASSWORD",
"billTerms": "PP",
"serviceType": "LTL",
"pickupDate": "2026-03-03",
"shipperInfo": {
"customerName": "Test Shipper Co",
"customerAddress": {
"streetAddress": "1202 Chalet Ln",
"city": "Harrison",
"state": "AR",
"zip": "72601"
}
},
"consigneeInfo": {
"customerName": "Widget Company",
"customerAddress": {
"streetAddress": "525 S Winchester Blvd",
"city": "San Jose",
"state": "CA",
"zip": "95128"
}
},
"items": {
"item": [
{
"description": "Industrial Equipment",
"pcs": 1,
"pallets": 1,
"weight": 500,
"actualClass": "70"
}
]
},
"accessorials": { "accessorial": [] }
}
}
Audit log (per request)
[
{ "step": 1, "name": "OAuth", "success": true, "durationMs": 520, "message": "Token obtained" },
{ "step": 2, "name": "RATE_QUOTE", "success": true, "durationMs": 2100, "message": "200 OK" }
]
BTX Air / LTL
Authentication
No OAuth or API key exchange. The CustomerID GUID is embedded directly in every SOAP request body. Authentication is effectively handled at the SOAP layer by the CustomerID.
{ "step": 1, "name": "BTX Auth", "success": true, "durationMs": 0, "message": "No OAuth – CustomerID embedded in request XML" }
Rate request
Mapped to a SOAP XML envelope sent via POST to the BTX web service endpoint with SOAPAction header.
Key transformations:
shipDate "2026-03-03"→"3/3/2026"(M/D/YYYY format required)weightunit →"Pounds"(full word, not abbreviation)length/width/heightunit →"Inches"serviceTypedefaults toLessThanTruckloadshipmentSubTypedefaults toGroundLTL
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<Rating xmlns="http://www.btxair.com/BTXWebServices/">
<CustomerID>3314DE8A-6881-4BDF-8971-C6BFA56D3C03</CustomerID>
<ShipFrom>
<Name>Test Shipper Co</Name>
<Address1>1202 Chalet Ln</Address1>
<City>Harrison</City>
<State>AR</State>
<PostalCode>72601</PostalCode>
<Country>US</Country>
<Phone>8705550100</Phone>
</ShipFrom>
<ShipTo>
<Name>Widget Company</Name>
<Address1>525 S Winchester Blvd</Address1>
<City>San Jose</City>
<State>CA</State>
<PostalCode>95128</PostalCode>
<Country>US</Country>
</ShipTo>
<FreightItems>
<FreightItem>
<Description>Industrial Equipment</Description>
<Hazmat>false</Hazmat>
<Length>48</Length>
<Width>40</Width>
<Height>48</Height>
<Pieces>1</Pieces>
<ExtActualWeight>500</ExtActualWeight>
<WeightUnit>Pounds</WeightUnit>
<DimUnit>Inches</DimUnit>
<ContainerType>Pallet</ContainerType>
</FreightItem>
</FreightItems>
<ShipDate>3/3/2026</ShipDate>
<ShipmentSubType>GroundLTL</ShipmentSubType>
<ServiceType>LessThanTruckload</ServiceType>
<COD>0</COD>
<DeclaredValue>0</DeclaredValue>
<InsuranceValue>0</InsuranceValue>
</Rating>
</Body>
</Envelope>
Audit log (per request)
[
{ "step": 1, "name": "BTX Auth", "success": true, "durationMs": 0, "message": "No OAuth – CustomerID embedded in request XML" },
{ "step": 2, "name": "RATE", "success": true, "durationMs": 2800, "message": "200 OK" }
]
Response Mapper
The mapper (scripts/response-mapper.js) normalizes each carrier's raw API response into a unified ShipEngine-style quote object. Each carrier returns a very different structure — the mapper extracts only the fields needed.
mapDaylightResponse()
mapBtxResponse()per-carrier function
If a carrier fails (auth error, API error, or unmappable response), its quote is null and error contains the message. The other carriers are unaffected.
FedEx Freight LTL — mapping
Raw response (simplified)
{
"output": {
"rateReplyDetails": [
{
"serviceType": "FEDEX_FREIGHT_ECONOMY",
"operationalDetail": { "transitDays": null },
"ratedShipmentDetails": [
{
"quoteNumber": "1155551343",
"totalBaseCharge": 2011.95,
"totalNetFedExCharge": 2700.38,
"totalDiscounts": 0.0,
"shipmentRateDetail": {
"surCharges": [
{ "description": "Fuel Surcharge", "amount": 661.93 },
{ "description": "Other", "amount": 26.50 }
]
}
}
]
}
]
}
}
Field mapping
| Raw field | Mapped to |
|---|---|
| rateReplyDetails[n].serviceType | service.code and service.carrier_description — one quote per array entry |
| ratedShipmentDetails[0].quoteNumber | carrier_quote_id |
| ratedShipmentDetails[0].totalBaseCharge | charges[] → container "Freight Charge" |
| shipmentRateDetail.surCharges[].description | charges[] → accessorial (one entry per surcharge) |
| ratedShipmentDetails[0].totalDiscounts | charges[] → discount (only if non-zero) |
| ratedShipmentDetails[0].totalNetFedExCharge | charges[] → total "Total Charge" |
| operationalDetail.transitDays | estimated_delivery_days (int or string enum → int) |
| carrier_message, effective_date, expiration_date, quote_id, quote_type, pickup_date | null — not returned by FedEx Freight LTL API |
surCharges (capital C). The mapper checks both surCharges and surcharges for resilience against API version changes.
Mapped output
[
{
"carrier_message": null,
"carrier_quote_id": "1155551343",
"charges": [
{ "type": "container", "description": "Freight Charge", "amount": { "currency": "USD", "value": "2011.95" } },
{ "type": "accessorial", "description": "Fuel Surcharge", "amount": { "currency": "USD", "value": "661.93" } },
{ "type": "accessorial", "description": "Other", "amount": { "currency": "USD", "value": "26.50" } },
{ "type": "total", "description": "Total Charge", "amount": { "currency": "USD", "value": "2700.38" } }
],
"effective_date": null,
"estimated_delivery_days": null,
"expiration_date": null,
"pickup_date": null,
"quote_id": null,
"quote_type": null,
"service": { "carrier_description": "FEDEX_FREIGHT_ECONOMY", "code": "FEDEX_FREIGHT_ECONOMY" },
"shipment": { "...echoed input shipment..." }
},
{
"carrier_message": null,
"carrier_quote_id": "1155551344",
"charges": [ "...FEDEX_FREIGHT_PRIORITY charges..." ],
"effective_date": null,
"estimated_delivery_days": null,
"expiration_date": null,
"pickup_date": null,
"quote_id": null,
"quote_type": null,
"service": { "carrier_description": "FEDEX_FREIGHT_PRIORITY", "code": "FEDEX_FREIGHT_PRIORITY" },
"shipment": { "...echoed input shipment..." }
}
]
Daylight LTL — mapping
Raw response
{
"dyltRateQuoteResp": {
"success": "YES",
"quoteNumber": "CQ444525",
"pickupDate": "03/03/2026",
"totalCharges": {
"grossCharge": 2740.95,
"fuelSurcharge": 46.38,
"discountAmt": 2576.49,
"netCharge": 284.91
},
"accessorialCharges": {
"accessorialCharge": [
{ "reqAccessorial": "CA Compliance", "accCharge": 12.50 },
{ "reqAccessorial": "Compliance Fee", "accCharge": 5.00 }
]
}
}
}
Field mapping
| Raw field | Mapped to |
|---|---|
| dyltRateQuoteResp.quoteNumber | carrier_quote_id |
| dyltRateQuoteResp.pickupDate | pickup_date |
| totalCharges.grossCharge | charges[] → container "Freight Charge" |
| totalCharges.fuelSurcharge | charges[] → accessorial "Fuel Surcharge" |
| accessorialCharges.accessorialCharge[] | charges[] → accessorial (each non-fuel item) |
| totalCharges.discountAmt | charges[] → discount "Discount" (only if non-zero) |
| totalCharges.netCharge | charges[] → total "Total Charge" |
| carrier_message, effective_date, expiration_date, quote_id, quote_type, estimated_delivery_days | null — not returned by Daylight LTL API |
dyltRateQuoteResp first, then falls back to dyltRateQuoteRes (without the trailing 'p'). estimated_delivery_days is always null — Daylight does not return transit days in rate quotes.
Mapped output
[
{
"carrier_message": null,
"carrier_quote_id": "CQ444525",
"charges": [
{ "type": "container", "description": "Freight Charge", "amount": { "currency": "USD", "value": "2740.95" } },
{ "type": "accessorial", "description": "Fuel Surcharge", "amount": { "currency": "USD", "value": "46.38" } },
{ "type": "accessorial", "description": "CA Compliance", "amount": { "currency": "USD", "value": "12.50" } },
{ "type": "accessorial", "description": "Compliance Fee", "amount": { "currency": "USD", "value": "5.00" } },
{ "type": "discount", "description": "Discount", "amount": { "currency": "USD", "value": "2576.49" } },
{ "type": "total", "description": "Total Charge", "amount": { "currency": "USD", "value": "284.91" } }
],
"effective_date": null,
"estimated_delivery_days": null,
"expiration_date": null,
"pickup_date": "03/03/2026",
"quote_id": null,
"quote_type": null,
"service": { "carrier_description": "LTL Standard", "code": "LTL" },
"shipment": { "...echoed input shipment..." }
}
]
BTX Air / LTL — mapping
Raw response
BTX returns SOAP/XML. The adapter parses it to JSON using @xmldom/xmldom. The mapper reads from the parsed .json tree.
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<RatingResponse xmlns="http://www.btxair.com/BTXWebServices/">
<RatingResult>
<Error>false</Error>
<TransitDays>6</TransitDays>
<Freight>504.67</Freight>
<Fuel>163.01</Fuel>
<TotalCost>809.46</TotalCost>
<Accessorials>
<RatedAccessorial>
<Description>West Coast Surcharge</Description>
<Cost>32.50</Cost>
</RatedAccessorial>
</Accessorials>
</RatingResult>
</RatingResponse>
</Body>
</Envelope>
Field mapping
| Raw field | Mapped to |
|---|---|
| RatingResult.Freight | charges[] → container "Freight Charge" |
| RatingResult.Fuel | charges[] → accessorial "Fuel Surcharge" |
| Accessorials.RatedAccessorial[].Description | charges[] → accessorial (each non-fuel item) |
| RatingResult.TotalCost | charges[] → total "Total Charge" |
| RatingResult.TransitDays | estimated_delivery_days (string → int) |
| carrier_message, carrier_quote_id, effective_date, expiration_date, quote_id, quote_type, pickup_date | null — not returned by BTX API |
Error: "false" is the success indicator. Any other value (including "true") means the carrier returned an error and quotes will be []. BTX does not return a carrier_quote_id.
Mapped output
[
{
"carrier_message": null,
"carrier_quote_id": null,
"charges": [
{ "type": "container", "description": "Freight Charge", "amount": { "currency": "USD", "value": "504.67" } },
{ "type": "accessorial", "description": "Fuel Surcharge", "amount": { "currency": "USD", "value": "163.01" } },
{ "type": "accessorial", "description": "West Coast Surcharge", "amount": { "currency": "USD", "value": "32.50" } },
{ "type": "total", "description": "Total Charge", "amount": { "currency": "USD", "value": "809.46" } }
],
"effective_date": null,
"estimated_delivery_days": 6,
"expiration_date": null,
"pickup_date": null,
"quote_id": null,
"quote_type": null,
"service": { "carrier_description": "BTX Ground LTL", "code": "LessThanTruckload" },
"shipment": { "...echoed input shipment..." }
}
]
Full /api/rates response — all 3 carriers
{
"durationMs": 13868,
"carriers": {
"FedEx Freight LTL": {
"status": 200,
"error": null,
"durationMs": 5200,
"auditLog": [
{ "step": 1, "name": "OAuth", "success": true, "durationMs": 559, "message": "Token obtained" },
{ "step": 2, "name": "RATE", "success": true, "durationMs": 4200, "message": "200 OK" }
]
},
"Daylight LTL": {
"status": 200,
"error": null,
"durationMs": 3100,
"auditLog": [
{ "step": 1, "name": "Auth", "success": true, "durationMs": 0, "message": "No auth required — credentials embedded in request body" },
{ "step": 2, "name": "RATE_QUOTE", "success": true, "durationMs": 3100, "message": "200 OK" }
]
},
"BTX_AIR": {
"status": 200,
"error": null,
"durationMs": 2800,
"auditLog": [
{ "step": 1, "name": "BTX Auth", "success": true, "durationMs": 0, "message": "No OAuth – CustomerID embedded in request XML" },
{ "step": 2, "name": "RATE", "success": true, "durationMs": 2800, "message": "200 OK" }
]
}
},
"quotes": [
{
"carrier": { "id": "FedEx Freight LTL" },
"carrier_message": null,
"carrier_quote_id": "1155551343",
"charges": [
{ "type": "container", "description": "Freight Charge", "amount": { "currency": "USD", "value": "2011.95" } },
{ "type": "accessorial", "description": "Fuel Surcharge", "amount": { "currency": "USD", "value": "661.93" } },
{ "type": "accessorial", "description": "Other", "amount": { "currency": "USD", "value": "26.50" } },
{ "type": "total", "description": "Total Charge", "amount": { "currency": "USD", "value": "2700.38" } }
],
"effective_date": null,
"estimated_delivery_days": null,
"expiration_date": null,
"pickup_date": null,
"quote_id": null,
"quote_type": null,
"service": { "carrier_description": "FedEx Freight Economy", "code": "FEDEX_FREIGHT_ECONOMY" },
"shipment": { "origin": { "city": "Harrison", "state": "AR" }, "...": "..." }
},
{
"carrier": { "id": "FedEx Freight LTL" },
"carrier_message": null,
"carrier_quote_id": "1155551344",
"charges": [
{ "type": "container", "description": "Freight Charge", "amount": { "currency": "USD", "value": "2214.15" } },
{ "type": "accessorial", "description": "Fuel Surcharge", "amount": { "currency": "USD", "value": "729.10" } },
{ "type": "total", "description": "Total Charge", "amount": { "currency": "USD", "value": "2970.42" } }
],
"effective_date": null,
"estimated_delivery_days": null,
"expiration_date": null,
"pickup_date": null,
"quote_id": null,
"quote_type": null,
"service": { "carrier_description": "FedEx Freight Priority", "code": "FEDEX_FREIGHT_PRIORITY" },
"shipment": { "origin": { "city": "Harrison", "state": "AR" }, "...": "..." }
},
{
"carrier": { "id": "Daylight LTL" },
"carrier_message": null,
"carrier_quote_id": "CQ444525",
"charges": [
{ "type": "container", "description": "Freight Charge", "amount": { "currency": "USD", "value": "2740.95" } },
{ "type": "accessorial", "description": "Fuel Surcharge", "amount": { "currency": "USD", "value": "46.38" } },
{ "type": "discount", "description": "Discount", "amount": { "currency": "USD", "value": "2576.49" } },
{ "type": "total", "description": "Total Charge", "amount": { "currency": "USD", "value": "284.91" } }
],
"effective_date": null,
"estimated_delivery_days": null,
"expiration_date": null,
"pickup_date": "03/03/2026",
"quote_id": null,
"quote_type": null,
"service": { "carrier_description": "LTL Standard", "code": "LTL" },
"shipment": { "origin": { "city": "Harrison", "state": "AR" }, "...": "..." }
},
{
"carrier": { "id": "BTX_AIR" },
"carrier_message": null,
"carrier_quote_id": null,
"charges": [
{ "type": "container", "description": "Freight Charge", "amount": { "currency": "USD", "value": "504.67" } },
{ "type": "accessorial", "description": "Fuel Surcharge", "amount": { "currency": "USD", "value": "163.01" } },
{ "type": "accessorial", "description": "West Coast Surcharge", "amount": { "currency": "USD", "value": "32.50" } },
{ "type": "total", "description": "Total Charge", "amount": { "currency": "USD", "value": "809.46" } }
],
"effective_date": null,
"estimated_delivery_days": 6,
"expiration_date": null,
"pickup_date": null,
"quote_id": null,
"quote_type": null,
"service": { "carrier_description": "BTX Ground LTL", "code": "LessThanTruckload" },
"shipment": { "origin": { "city": "Harrison", "state": "AR" }, "...": "..." }
}
]
}
Accessorials
LTL accessorials are additional fees for services beyond standard dock-to-dock transportation (liftgates, residential delivery, inside service, etc.). The aggregator translates normalized codes from NetSuite into each carrier's specific API format.
[{code: "LIFTGATE_DELIVERY"}] → aggregator accessorial-mapper.js → per-carrier format → carrier API
The mapper module (scripts/accessorial-mapper.js) handles:
- Translation — normalized code → carrier-specific format
- Filtering — unsupported codes per carrier are silently dropped
- Deduplication — e.g. Construction + Limited Access collapse to one Daylight entry
- Dual input — accepts both
["CODE"]and[{code: "CODE"}]
Complete Mapping Table
Source of truth: docs/reference/research_accessorials.md + official carrier API guides.
| # | Normalized Code | Description | FedEx | Daylight accName / accId | BTX ID |
|---|---|---|---|---|---|
| 1 | LIFTGATE_DELIVERY | Liftgate Delivery | LIFTGATE_DELIVERY | D / Lift Gate Delivery | 216 |
| 2 | LIFTGATE_PICKUP | Liftgate Pickup | LIFTGATE_PICKUP | P / Lift Gate Pickup | 215 |
| 3 | INSIDE_DELIVERY | Inside Delivery | INSIDE_DELIVERY | D / Inside Delivery | 202 |
| 4 | INSIDE_PICKUP | Inside Pickup | INSIDE_PICKUP | P / Inside Pickup | 206 |
| 5 | RESIDENTIAL_DELIVERY | Residential Delivery | RESIDENTIAL_DELIVERY | D / Residential Delivery | 271 |
| 6 | RESIDENTIAL_PICKUP | Residential Pickup | RESIDENTIAL_PICKUP | — | 270 |
| 7 | LIMITED_ACCESS_DELIVERY | Limited Access Delivery | LIMITED_ACCESS_DELIVERY | D / Limited Access or Construction Site Delivery | — |
| 8 | LIMITED_ACCESS_PICKUP | Limited Access Pickup | LIMITED_ACCESS_PICKUP | P / Limited Access or Construction Site Pickup | — |
| 9 | CONSTRUCTION_DELIVERY | Construction Site Delivery | — | D / Limited Access or Construction Site Delivery | 52 |
| 10 | CONSTRUCTION_PICKUP | Construction Site Pickup | — | P / Limited Access or Construction Site Pickup | 70 |
| 11 | APPOINTMENT_DELIVERY | Appointment Delivery | DELIVERY_APPOINTMENT_NOTIFICATION | D / Appointment Fee | 121 |
| 12 | APPOINTMENT_PICKUP | Appointment Pickup | — | — | 120 |
| 13 | HAZMAT | Hazardous Material | HAZARDOUS_MATERIALS | — | FreightItem.Hazmat |
| 14 | OVERLENGTH | Over Dimension / Length | OVER_LENGTH | O / Overlength 8 ft but less than 12 ft | — |
| 15 | GUARANTEED | Guaranteed Service | FREIGHT_GUARANTEE | — | — |
| 16 | NOTIFY_CONSIGNEE | Must Notify Consignee | CALL_BEFORE_DELIVERY | — | — |
| 17 | PROTECT_FROM_COLD | Protective From Cold | PROTECTION_FROM_FREEZING | — | — |
| 18 | CA_COMPLIANCE | CA Compliance Surcharge | — | O / Compliance Services Fee | — |
Coverage: FedEx 14 codes · Daylight 12 codes · BTX 10 codes. Remaining 18 NS codes (COD, Fuel Surcharge, In Bond, etc.) have no carrier mapping and are silently filtered.
FedEx Freight LTL
Accessorials are injected into freightRequestedShipment.freightShipmentSpecialServices.specialServiceTypes[] as enum strings.
Rate: Included when mapped array is non-empty. Booking/Pickup: N/A — accessorials are applied at rate time, not in the pickup API.
Source: FedEx API Reference — Freight Special Services
{
"freightRequestedShipment": {
"freightShipmentSpecialServices": {
"specialServiceTypes": ["LIFTGATE_DELIVERY", "INSIDE_DELIVERY", "RESIDENTIAL_DELIVERY"]
}
}
}
Daylight LTL
Accessorials are injected into accessorials.accessorial[] with accName (P/D/O category) and accId (exact service name string).
Rate & Booking: Same structure for both operations.
Source: Daylight API Overview · Rate Quote Schema
{
"accessorials": {
"accessorial": [
{ "accName": "D", "accId": "Lift Gate Delivery" },
{ "accName": "D", "accId": "Inside Delivery" },
{ "accName": "D", "accId": "Residential Delivery" }
]
}
}
CONSTRUCTION_DELIVERY + LIMITED_ACCESS_DELIVERY map to the same accId — mapper deduplicates automatically.BTX Air / LTL
Accessorials are injected into <Accessorials><Accessorial><ID>integer</ID></Accessorial> XML elements. IDs are numeric integers, not strings.
Rate & Booking: Same structure for both operations. HAZMAT: Handled at FreightItem.Hazmat boolean level, not as an accessorial.
Source: BTX Rating Web Service Implementation Guide v3.8 (8/6/2024) · Booking Guide v4.0 (11/19/2024)
<Accessorials>
<Accessorial>
<ID>216</ID>
<Description>Liftgate DL</Description>
</Accessorial>
<Accessorial>
<ID>202</ID>
<Description>Inside DL</Description>
</Accessorial>
<Accessorial>
<ID>271</ID>
<Description>Residential DL</Description>
</Accessorial>
</Accessorials>
| ID | Description | ID | Description |
|---|---|---|---|
| 216 | Liftgate DL | 215 | Liftgate PU |
| 202 | Inside DL | 206 | Inside PU |
| 271 | Residential DL | 270 | Residential PU |
| 121 | Appointment DL | 120 | Appointment PU |
| 52 | Construction Site DL | 70 | Construction Site PU |
NS Input Contract
NetSuite sends normalized accessorial codes in the shipment.accessorials array. Each entry is an object with a code property:
{
"shipment": {
"origin": { "..." },
"destination": { "..." },
"items": [ "..." ],
"shipDate": "2026-04-01",
"accessorials": [
{ "code": "LIFTGATE_DELIVERY" },
{ "code": "INSIDE_DELIVERY" },
{ "code": "RESIDENTIAL_DELIVERY" }
]
}
}
The aggregator stores accessorials in the KV quote snapshot so the pickup/booking endpoint can inherit them without NS re-sending.
Live Test Results (2026-03-25)
| Carrier | Baseline | With Liftgate + Inside + Residential | Increase |
|---|---|---|---|
| FedEx Priority | $3,036.29 | $3,686.29 | +$650.00 |
| FedEx Economy | $2,748.49 | $3,398.49 | +$650.00 |
| BTX LTL | $900.49 | $1,744.24 | +$843.75 |
| Daylight LTL | Empty charges (pre-existing route/config issue — not accessorial-related) | ||
Error handling
Each carrier is called independently. A failure in one does not block the others — the failed carrier's entry in carriers gets a non-null error message and contributes no quotes to the top-level quotes[] array.
Auth failure
{
"durationMs": 600,
"carriers": {
"FedEx Freight LTL": {
"status": 401,
"error": "OAuth failed: NOT.AUTHORIZED.ERROR (HTTP 401)",
"durationMs": 600,
"auditLog": [
{ "step": 1, "name": "OAuth", "success": false, "durationMs": 600, "message": "OAuth failed: NOT.AUTHORIZED.ERROR (HTTP 401)" }
]
}
},
"quotes": []
}
API error after successful auth
{
"durationMs": 5100,
"carriers": {
"FedEx Freight LTL": {
"status": 400,
"error": "RATE error (HTTP 400): Entered freight account number could not be validated.",
"durationMs": 5100,
"auditLog": [
{ "step": 1, "name": "OAuth", "success": true, "durationMs": 559, "message": "Token obtained" },
{ "step": 2, "name": "RATE", "success": false, "durationMs": 4200, "message": "HTTP 400" }
]
}
},
"quotes": []
}
HTTP error codes
| Status | Meaning |
|---|---|
| 200 | Success — all carriers processed (some may have errors in their individual result) |
| 401 | Missing or invalid X-Api-Key header |
| 400 | Missing or unknown carrierId on /api/pickup |
| 403 | Admin access required (non-admin key used on admin endpoint) |
| 405 | Wrong HTTP method |
| 500 | Unexpected server error (e.g. malformed JSON body) |
Admin — Customer Onboarding
Single endpoint for all customer management. Requires admin API key (isAdmin: true).
Create a new customer, update an existing one, rotate their API key, or revoke access.
Create / Update a customer
If clientId is new, generates an API key and returns it. If clientId already exists, updates the record (merges credentials).
curl -X POST https://logiveoaggregator.vercel.app/api/admin/onboard \
-H "X-Api-Key: ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"clientId": "acme-corp",
"clientName": "ACME Corporation",
"env": "production",
"credentials": {
"fedex": {
"clientId": "their-fedex-client-id",
"clientSecret": "their-fedex-client-secret",
"accountNumber": "123456789"
},
"daylight": {
"key": "their-key",
"secret": "their-secret",
"accountNumber": "DY-ACME",
"userName": "acme_user",
"password": "acme_pass"
},
"btx": {
"customerId": "their-btx-guid"
}
}
}'
Response (new customer)
{
"clientId": "acme-corp",
"clientName": "ACME Corporation",
"apiKey": "lgv_sk_...",
"env": "production",
"created": true
}
X-Api-Key header.
Rotate API key
{ "action": "rotate", "clientId": "acme-corp" }
Generates new key, revokes old. Returns newApiKey.
Revoke access
{ "action": "revoke", "clientId": "acme-corp" }
Sets active: false. Customer's API key stops working immediately.
List all clients
Returns all onboarded customers with masked API keys.
Response
{
"clients": [
{
"clientId": "acme-corp",
"clientName": "ACME Corporation",
"active": true,
"env": "production",
"apiKey": "lgv_***",
"carriers": ["fedex", "daylight", "btx"],
"createdAt": "2026-03-04T..."
}
]
}
Credential resolution
When a customer calls /api/rates or /api/pickup, credentials are resolved in this order:
Customers without their own credentials use Logiveo's env var credentials. No per-request KV lookups needed.
Admin — Audit Logs
Returns recent audit log entries for a given customer. Requires admin API key.
Sandbox notes
The server is currently configured for sandbox/test environments. Real shipment quotes require production credentials.
| Carrier | Sandbox URL | Notes |
|---|---|---|
| FedEx Freight LTL | apis-sandbox.fedex.com | Sandbox LTL account: 510087020. Origin must be 1202 Chalet Ln, Harrison AR 72601. Account 740561073 is production/parcel — do not use for LTL sandbox. |
| Daylight LTL | test-api.dylt.com | OAuth and rate URLs use double-slash (//oauth/... and //rateQuote). This is required by the API gateway. |
| BTX Air / LTL | btxapi.btxglobal.com | Same URL for sandbox and production. The CustomerID GUID controls which account is billed. No separate sandbox environment. |
Accept-Encoding: gzip and decompress the response. The server handles this automatically — no action needed from API consumers.