JP Express Integration Guide
Integrate FTM with JP Express SOAP API to fetch LTL rates from a Lane Quote and display the net charge in Salesforce.
Overview
The JPEX integration allows FTM users to:
- Request LTL rate quotes from JP Express via SOAP
- Parse the net charge from the XML response
- Show the result on the Lane Quote page/controller context
This integration authenticates with username/password and posts a SOAP Envelope to JPEX’s GetRates operation.
1️⃣ User Information
Purpose
Pull a quick JP Express rate for a domestic LTL shipment directly from a Lane Quote.
Workflow (User Perspective)
- Open a Lane Quote in Salesforce.
- Click “Get Rates (JP Express)” on the VF/LWC action.
- The system calls JP Express, parses the net charge, and returns one value (or “No service availability”).
Booking is not implemented in this class; this is a rate-only integration.
Key Features
- SOAP GetRates call to JP Express
- NMFC Class mapping from Lane Quote to JPEX class codes
- Payor & payment method support (Shipper/Consignee; PrePaid/Collect, etc.)
- Handles COD flag and placeholders for accessorials
- Graceful “No service availability” fallback
What You’ll See in Salesforce
- A single net charge value (string) available via controller static netFc
- Debug logs with request/response traces for troubleshooting
Supported Use Cases
- Rapid point rate check for LTL with JP Express (U.S.)
Prerequisites
- Credentials on User (CreatedBy of Lane Quote):
- Jp_User_Name__c
- Jp_Password__c
- Jp_Express_Account_Number__c
- Lane Quote fields populated:
- Pickup/Delivery Zip, City, State, Country
- Freight Class, Weight, Handling Units
- Role__c (Payee), PaymentMethod__c, **isCod__c`
- Remote Site Setting for:
- https://webapi.myjpexpress.com
- Apex Class Access:
- JpExInteg
- (Recommended) Store credentials in Protected Custom Metadata/Setting instead of on User.
2️⃣ Developer Information
Apex Components
| Component | Purpose |
| JpExInteg | Visualforce controller that builds the SOAP XML, calls JPEX, and parses net charge |
Authentication
- Username/Password from the Lane Quote CreatedBy user:
- CreatedBy.Jp_User_Name__c
- CreatedBy.Jp_Password__c
- CreatedBy.Jp_Express_Account_Number__c (rate account)
Tip: Move these into JpExpress_Config__mdt (Protected) with fields Username__c, Password__c, Account_Number__c, then reference via getInstance(‘Default’).
Endpoint & Operation
| Purpose | Method | URL | SOAPAction |
| Get Rates | POST | https://webapi.myjpexpress.com/JpeWs.asmx | http://jpxpress.com/GetRates (recommended to include) |
HTTP Headers
- Content-Type: text/xml
- Accept: */*
- SOAPAction: http://jpxpress.com/GetRates (add this header, some SOAP stacks require it even if not always enforced).
Field Mapping (Lane Quote → JPEX)
| Source (Salesforce) | JPEX Field | Notes |
| CreatedBy.Jp_User_Name__c | userName | Auth |
| CreatedBy.Jp_Password__c | password | Auth |
| CreatedBy.Jp_Express_Account_Number__c | rateAccount | Auth/account |
| Role__c | payee | e.g., Shipper/Consignee |
| PaymentMethod__c | paymentMethod | e.g., PrePaid/Collect |
| FreightTM__Pickup_Zip_Code__c | originZip | ZIP only |
| FreightTM__Delivery_Zip_Code__c | destZip | ZIP only |
| Weight_Value__c | parameters[].Weight | Integer in lbs |
| Freight_Class__c | parameters[].Class | Mapped (below) |
| Handling_Units__c | parameters[].Pallets | Integer |
| isCod__c | isCod | Boolean |
Freight Class Mapping (as used in code)
CLASS_050→0500, CLASS_055→0550, CLASS_060→0600, CLASS_065→0650,
CLASS_070→0700, CLASS_077_5→0775, CLASS_085→0850, CLASS_092_5→0925,
CLASS_100→1000, CLASS_110→1100, CLASS_125→1250, CLASS_150→1500,
CLASS_175→1750, CLASS_200→2000, CLASS_250→2500, CLASS_300→3000,
CLASS_400→4000, CLASS_500→5000
How It Works
- Controller loads Lane Quote and CreatedBy credential fields.
- Builds a SOAP Envelope for GetRates, including one or more <RateParameter> items (Weight, Class, Pallets).
- POST to JpeWs.asmx.
- Parses XML for <Rates><decimal> and assigns netFc:
- If value is 0 or cannot be parsed ⇒ netFc = ‘No service availability’
- Else ⇒ netFc = String.valueOf(rateDecimal)
Sample SOAP Request (Trimmed)
POST /JpeWs.asmx HTTP/1.1
Host: webapi.myjpexpress.com
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://jpxpress.com/GetRates"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetRates xmlns="http://jpxpress.com/">
<userName>USERNAME</userName>
<password>PASSWORD</password>
<rateAccount>ACCOUNT</rateAccount>
<payee>Shipper</payee>
<paymentMethod>PrePaid</paymentMethod>
<originZip>19342</originZip>
<destZip>17506</destZip>
<parameters>
<RateParameter>
<Weight>300</Weight>
<Class>5000</Class>
<Pallets>1</Pallets>
</RateParameter>
</parameters>
<isCod>false</isCod>
<codAmount>string</codAmount>
<accessorials>
<string>string</string>
<string>string</string>
</accessorials>
</GetRates>
</soap:Body>
</soap:Envelope>
Sample Response Snippet (Trimmed)
<GetRatesResponse xmlns="http://jpxpress.com/">
<GetRatesResult>
<Rates>
<decimal>1125.50</decimal>
</Rates>
</GetRatesResult>
</GetRatesResponse>
Parsing Logic
- The controller extracts the first <Rates><decimal> value.
- If absent, unparsable, or equals 0 → netFc = ‘No service availability’.
- Otherwise → netFc = String.valueOf(parsedDecimal).
Note: This is a string output for UI friendliness.
If you need arithmetic, store a Decimal field on Lane Quote (e.g., JPEX_Net_Charge__c) and assign it there.
Error Handling
| Condition | Outcome |
| Non-200 HTTP | netFc = ‘No service availability’ (and debug logs) |
| Missing <Rates><decimal> | netFc = ‘No service availability’ |
| Parsed value = 0 | netFc = ‘No service availability’ |
| Exceptions | Caught; netFc falls back; details in logs |
Security Recommendations
- Do not store credentials on the user long-term. Move to Protected Custom Metadata/Setting:
- JpExpress_Config__mdt(Username__c, Password__c, Account_Number__c)
- Never commit credentials to Git.
- Consider Named Credential for endpoint allowlisting (still SOAP body-auth for this API).
Testing
Anonymous Apex
JpExInteg.sendRequest('a0HXXXXXXXXXXXX'); // Lane Quote Id
System.debug(JpExInteg.netFc); // Expect a string value or 'No service availability'
From UI
- Add a button or VF quick action that calls getData() on JpExInteg.
Deployment Checklist
✅ Remote Site Setting: https://webapi.myjpexpress.com
✅ Apex class access: JpExInteg
✅ Required Lane Quote fields populated (zip/weight/class/handling units)
✅ Credentials configured (User or Protected CMDT)
✅ (Recommended) Add SOAPAction header
Limitations
- Rates only (no booking flow in this class)
- Expects valid U.S. ZIPs
- Response parsing assumes first <Rates><decimal> represents the net charge
- Accessorials are placeholders (<string>string</string>) map real codes when available
FAQ
Q: Can we pass multiple pallets/classes?
A: Yes. Add multiple <RateParameter> elements to the parameters list.
Q: Where do we show the rate?
A: Currently exposed as the static netFc string in the controller; wire it to your VF/LWC and/or persist to a field.
Q: Do we need the SOAPAction header?
A: Often yes for classic .asmx SOAP services. Add SOAPAction: http://jpxpress.com/GetRates.
Support
📧 FTM Integration Support: [email protected]
