New: Odoo and Dynamics 365 cost calculators.Estimate your costs

Shipping ERP: carrier rates, labels, and freight billing

Shipping ERP means the sales order, the label, and the freight cost stay together.

FlecticUpdated 24 min read

Shipping ERP means the sales order, the label, and the freight cost stay together. As of October 2026, Business Central shipping agents and package tracking cover agent codes, a service time on the sales line, a package number you enter, and a link to the carrier site. Rate shopping and label purchase sit outside those pages. Odoo 19 documents Get Rate and label creation for named carriers, and EasyPost inside Odoo as the North American multi-carrier path. EasyPost pricing lists a USD 0 platform fee up to 3,000 labels, postage excluded, as of October 2026.

ShipStation does not appear on that Odoo 19 connector list. ShipStation's rate shopper page says it rate-shops 200+ parcel carriers and 50+ LTL freight carriers, supports bring-your-own carrier accounts, and books LTL in the same workflow as parcel. The same page claims exclusive discounts of 80% to 90% from major carriers. Treat those lines as vendor claims, and keep them out of an ERP savings model. For a US distributor or e-commerce shipper, the choice is whether the documented ERP path buys the label, or a connected tool does, and whether the freight amount then hits the order.

What the shipping desk has to finish

A useful shipping setup closes four jobs on the same order. Someone sees a rate before the label is bought, or they have already chosen a single carrier and accept that carrier's price. The label prints from the delivery, with a tracking number stored on that delivery. The customer can be pointed at the carrier's tracking page. The freight dollars land on the shipment or the invoice in a way finance can tie to the carrier bill.

Postage websites already do the first two jobs for one carrier at a time. USPS, UPS, and FedEx will quote, print, and track on their own sites. They will not post a charge to your sales order, and they will not compare a second carrier inside your item list. That gap is why an operations lead shopping for shipping ERP is usually shopping for a posting design, with labels attached.

Business Central and Odoo split that design differently, which is the same native-versus-connected question covered in ERP integrations vs native modules. Business Central's published shipping pages stop at the agent, the transit time, the typed tracking number, and item charges for freight. Odoo's published path can request a rate and create a shipment for a named carrier, then still needs a manual edit when the billed cost replaces the estimate. A separate rate shop is the extra system when one delivery method cannot see every carrier you use, especially when parcel and LTL share a bench.

Wholesalers who already run orders, inventory, and invoicing in the cloud hit this at go-live or at the first peak season after go-live. The cloud ERP for wholesale distribution pattern still leaves carrier credentials, package setup, and freight posting as their own work.

What Business Central documents for shipping agents

A shipping agent in Business Central is a code plus descriptive data. An internet address on the agent turns on automatic package tracking when that agent offers tracking on the internet. Each agent can hold an unlimited number of services. Each service can carry a shipping time, and that time is included in order promising on the sales order line. If your promise date depends on ground versus two-day, the service time is the native field that feeds it.

Package tracking, as documented, starts from a posted sales shipment, a posted sales invoice, a posted sales credit memo, or a posted return receipt. The user enters the package number received from the shipping agent in Package Tracking No., confirms the agent and the service, and uses Track Package. Track Package opens the agent's tracking site. The number originates outside Business Central, on the carrier site or in whatever tool bought the label.

Those two pages are the native shipping module for this decision. They set up the agent, store a service time, accept a tracking number a person typed, and link out. Rate shopping, label purchase, and a carrier API charge written back onto the sales order sit outside those two pages. If a bidder's demo shows live UPS and FedEx rates inside Business Central, that behavior is coming from an extension or from a connected product. Ask them to name the extension, the carrier accounts it calls, and who owns the code when the carrier changes an API.

For a single-entity distributor that already has a negotiated account with one parcel carrier, the native agent can be enough for promising and for customer service lookups. The warehouse still buys the label somewhere else, and someone still has to type the tracking number before Track Package does anything. The moment the bench compares two carriers, or LTL has to be booked next to parcel, you are in connector scope. Microsoft's own pages are the boundary. Have any claimed rate shop shown on your items, your weights, and your accounts.

How freight reaches the sales shipment in Business Central

Labels are visible. The quieter failure is a carrier invoice in accounts payable that never touches the order that caused it. Business Central's tool for that extra cost is the item charge. Item charges cover freight, insurance, handling, and customs duty. On sales shipments, freight-out is a non-inventoriable item charge. It does not increase inventory value. It posts to Cost Amount (Non-Invtbl.). It shows in the item's profit and sales statistics. Margin on the shipment can see the freight, and the inventory balance stays on the product cost you already had.

Assignment can be suggested Equally, By Amount, By Weight, or By Volume. By Weight and By Volume use Net Weight and Unit Volume on the item card. A charge can be assigned on the original document, or later from a separate invoice to posted sales shipment lines. That second path matches carrier bills that arrive days after the truck left.

  • Equally (What it needs on the item: Nothing beyond the lines you assign · When it fits: A flat fee you intend to spread without regard to size or price)
  • By Amount (What it needs on the item: Line amounts · When it fits: Freight that should follow selling price)
  • By Weight (What it needs on the item: Net Weight · When it fits: Parcel and freight bills that follow pounds)
  • By Volume (What it needs on the item: Unit Volume · When it fits: Bulky goods where cubes drive the charge)

If Net Weight is blank, By Weight has nothing reliable to use. Fill Net Weight and Unit Volume before you train the team on those suggestions. A demo database with weights already filled will hide this. Run the suggestion on a real item that shipping has complained about.

Microsoft's landed-cost example is a purchase receipt: 100 units at USD 10.00 each, plus USD 200 freight and USD 100 customs duty assigned to the receipt. Landed cost becomes USD 13.00 per unit, and cost of goods sold uses USD 13.00. The unit price before freight and duty was USD 10.00. That example is inbound freight and duty on a receipt. Outbound freight-out on a sales shipment stays non-inventoriable, so a parcel label fee does not recost inventory the way this receipt does.

Timing changes the margin picture. If an item charge is posted after the item is sold, cost of goods sold does not update by itself. The Adjust Cost - Item Entries batch job has to forward the extra cost to the outbound entries. On standard-cost items, the charge does not change the unit cost. Business Central posts the difference as a purchase variance. A controller who looks at standard cost the week of the shipment, then at the carrier bill the next month, will see the freight in variance after that batch runs. Put the batch on the month-end checklist, and name an owner.

Assume a sales shipment of two lines and a USD 80 freight-out charge you assign by weight. Item A is 10 units with Net Weight of 2 lb each, so 20 lb. Item B is 4 units with Net Weight of 5 lb each, so 20 lb. If By Weight follows total pounds, the USD 80 splits into USD 40 and USD 40 because the pounds match. By Amount would follow the line amounts instead. If item A's Net Weight is empty, that even split is not available, and the clerk will fall back to Equally or By Amount and the carrier bill will not match the goods that traveled.

This posting design is the part of the project that is larger than a label printer. Credentials, weights, and the item-charge routine belong in the same phase as whatever tool buys the label. Our logistics and supply chain implementation work treats that posting as scope, alongside the carrier connection.

How Odoo 19 gets a rate, a label, and an invoice line

Odoo 19's documented connectors are DHL Express (all regions; other DHL services are not supported), Envia.com, FedEx, UPS, US Postal Service (United States), Sendcloud, Bpost, EasyPost, Shiprocket, and Starshipit. Sendcloud is for shipments from Austria, Belgium, France, Germany, Italy, the Netherlands, Spain, and the United Kingdom, to any European country. Bpost covers Belgium, and Shiprocket covers India. Starshipit is Australia and New Zealand. EasyPost is the North American multi-carrier connector. A US warehouse choosing among UPS, FedEx, and USPS is looking at those direct connectors or at EasyPost, and at Sendcloud only if the origin is one of those European countries.

Delivery methods have two integration levels. Get Rate puts an estimated cost on the sales order or the invoice. Get Rate and Create Shipment also generates the label. Invoicing Policy can be Estimated cost from the carrier, or Real cost. On a quotation, Add Shipping and then Get Rate fills Cost from the total order weight, or from the sum of product weights, and from the distance between the warehouse address and the customer address. The delivery charge is added as the delivery product line. The customer can see a shipping line before you pick.

Validating the delivery order requests the carrier tracking number and puts the label PDF in the chatter, as described on Odoo's shipping label page. One label is generated per package. Tracking Reference sits on the delivery order's Additional Info tab. The Tracking button opens the carrier site. A three-package order is three labels and three tracking events. A pack table that expects one print for the whole order will miss two of them.

The documented path for invoicing the real shipping cost is manual. Create the invoice with the delivery product at a unit price of zero, edit Unit Price on the draft invoice to the real cost, and confirm. An automatic import of the carrier's billed invoice is outside that page. Estimated cost can go out with the quotation. Real cost, in the documentation, is a person typing the figure the carrier charged before the invoice is confirmed. If nobody does that edit, you bill the estimate, or you bill zero, and the carrier's later invoice sits in the same unmatched bucket Business Central item charges are meant to close.

Pick the integration level from the desk you have.

  1. Use Get Rate when sales must quote a delivery line and the warehouse will buy the label in a carrier portal or a separate tool. You still need a procedure for replacing the estimate with the billed amount.
  2. Use Get Rate and Create Shipment when the packer should buy the label from the delivery order and the carrier on that delivery method is the carrier you want.
  3. Keep one direct delivery method per carrier account. UPS on one method, FedEx on another, USPS on a third. The picker compares them by trying the methods, unless you put EasyPost in front.

Product weight is required. Get Rate reads order weight or the sum of product weights. A catalog with zero weights will price every carton the same, or it will error. Fix weights in the item master before you judge the connector.

When EasyPost fits, and when a separate rate shop fits

EasyPost inside Odoo connects UPS, USPS, FedEx, DHL, and other carriers enabled on the EasyPost account. It rates by package size and weight, charges the EasyPost account, and prints labels. Label formats are PNG, PDF, ZPL, or EPL2, so a thermal printer that wants ZPL can be fed from the same connector as a PDF that goes to the chatter. Test labels are cancelled immediately. Production labels are charged.

That is the documented way to load several US carrier accounts inside Odoo and rate by the package in front of the packer. A direct UPS delivery method only talks to UPS. EasyPost is what you turn on when the bench should see more than one of those accounts on the same shipment. Postage is still the carrier's price. EasyPost's platform fee is a separate line, covered below.

ShipStation remains the connect case when the requirement is a single rate shop that includes LTL with parcel. Odoo 19's connector page does not list ShipStation. ShipStation's rate shopper page claims 200+ parcel carriers and 50+ LTL carriers in one workflow, with bring-your-own accounts. If your floor books a parcel carton and a pallet on the same afternoon, ask the rate-shop vendor to show both on your lanes. Then decide how the chosen cost gets back to the Odoo delivery product or the Business Central item charge.

Calls that Odoo initiates to delivery carriers such as UPS, FedEx, DHL, and similar are part of the Standard plan, not the External API. The External API, which is Custom plan only, is when outside software calls Odoo's JSON-RPC or XML-RPC API. A ShipStation-style tool that calls into Odoo is that second case. Budget the Custom plan if the shipping tool pushes orders and tracking into Odoo. Budget Standard if Odoo is the system that calls UPS, FedEx, USPS, or EasyPost. Confirm the direction of the calls on a diagram before you pick the plan. We do not resell ShipStation or EasyPost. The implementation question is credentials, field mapping, and freight posting.

If the tool only needs a tracking number typed back into Business Central, the native Package Tracking No. field is the landing spot, and you have accepted the re-key. If the tool must create the label and write the cost without a clerk, that interface is project scope. System integration is the work of making those calls, mappings, and retries explicit.

What the ERP license costs, separate from postage

License list prices do not buy labels. As of October 2026, Business Central US pricing lists Essentials at USD 80.00 per user per month, Premium at USD 110.00, and Team Members at USD 8.00, paid yearly. The page says prices are informational and the checkout price can differ by currency, country, and region. None of these licenses is a shipping-connector fee.

  • Business Central Essentials (List price as of October 2026: USD 80.00 · Basis: Per user per month, paid yearly)
  • Business Central Premium (List price as of October 2026: USD 110.00 · Basis: Per user per month, paid yearly)
  • Business Central Team Members (List price as of October 2026: USD 8.00 · Basis: Per user per month, paid yearly)

Assume 10 people need Essentials because they enter orders, post shipments, or assign item charges, and 6 people only need Team Members for lookups. At those list prices the Essentials portion is USD 800.00 per month and the Team Members portion is USD 48.00 per month, USD 848.00 per month before any checkout adjustment. Premium for the same 10 people would be USD 1,100.00 per month before Team Members. For a single-entity distributor under 30 users, Essentials is usually enough for finance, sales, and inventory. Premium is a manufacturing and service discussion, and it still does not add rate shopping to the shipping-agent pages.

Odoo pricing, as rendered for the US, shows two pairs on the Standard card: 24.90 and 31.10 in the yearly and monthly widget, and also USD 31.10 and USD 38.90 printed on the same card. The Custom card shows 49.00 and 61.10 in the widget, and also USD 61.00 and USD 76.20. An asterisk says the discount is valid for 12 months for the initial users ordered. Do not collapse either card into one number. For 10 users, the Standard widget figures become USD 249.00 and USD 311.00 per month. The other printed pair becomes USD 311.00 and USD 389.00 per month. Custom's four figures become USD 490.00, USD 611.00, USD 610.00, and USD 762.00 per month for those same 10 users. Recheck the card at checkout, then multiply.

Odoo.sh hosting is extra on Custom. Custom is also the plan that includes the External API, multi-company, and Studio, along with Odoo Online, Odoo.sh, or on-premise. A light user is listed at USD 8.90 and includes the inventory barcode operator among limited duties. Light users are sold after an advisor quote, not as self-serve checkout on that page. Ask which shipping buttons a light user can press. The pricing page names the barcode operator, and it does not itemize Get Rate or label purchase for that seat.

EasyPost pricing as of October 2026, for the connector Odoo documents:

  • Suite, wallet carriers (Amount: USD 0 platform fee up to 3,000 labels, then a per-label fee · What it covers: Postage not included. The fee above 3,000 labels is not given as a number)
  • Bring-your-own carrier accounts (Amount: USD 20 per month, plus a per-label fee · What it covers: The per-label fee is not numbered on the page)
  • Tracking API (Amount: USD 0.01 to USD 0.03 · What it covers: Per shipment)
  • Advanced Tracking (Amount: USD 0.03 · What it covers: Per shipment)
  • Insurance and Claims API (Amount: 1% of shipment value, minimum USD 1.00 · What it covers: Per insured shipment)

Assume 2,500 labels in a month on wallet carriers. The platform fee at that volume is USD 0, and you still pay postage. Add Tracking API and the same 2,500 shipments cost USD 25.00 at USD 0.01 each, or USD 75.00 at USD 0.03 each. A USD 200 insured parcel is USD 2.00 at 1%. A USD 40 insured parcel hits the USD 1.00 minimum, because 1% of USD 40 is USD 0.40. Cross 3,000 labels and the unnamed per-label platform fee starts. Ask EasyPost for that amount, and for the bring-your-own per-label fee, before you model November.

Odoo Success Packs for new customers, with 15% off the first pack, list USD 493, USD 3,060, USD 5,950, USD 10,625, and USD 21,250 for Starter through Pro: 4, 25, 50, 100, and 200 hours. Returning-customer prices on the same table are USD 580, USD 3,600, USD 7,000, USD 12,500, and USD 25,000. Those are generic consultant-hour bundles. They are not a quote for carrier mapping, weight cleanup, or freight posting. Ask each bidder to price data cleanup, carrier credentials, and freight allocation as their own lines.

Where the integration fails after the demo

Demos use a clean warehouse address, a product that already has weight, and a test flag. Production fails on the data the carrier checks.

Odoo warns that switching a delivery method from Test Environment to Production creates real labels and can charge the carrier account before the customer is billed. Leave the method in test until a packer has printed a label you are willing to throw away. Test labels on the EasyPost connector are cancelled immediately. Production labels are charged. Test mode, as documented, is the state before that switch. Flipping the method to production is what can charge the carrier account.

Warehouse address, including ZIP, and phone must match the carrier's records. Product weight is required. Get Rate errors are tied to a bad warehouse address or missing weights. Fix the company record the carrier has on file before you debug code. A suite number the carrier does not store will fail the same way a wrong ZIP fails.

When the Odoo estimate and the carrier price disagree, compare three things: a shipment created on the carrier site, the Odoo estimate, and the debug HTTP log. Odoo's example is a request that says six kilograms and a FedEx response that says seven kilograms, which Odoo treats as a carrier-side mismatch. The log is the artifact to keep. A screenshot of the sales order alone will not show that the carrier reweighed the call.

Package type is the next rejection after weight. Rate by the package size the carrier will accept, which is how EasyPost rates, and confirm the package code on a live test shipment. One label is generated per package. If customer service expects a single tracking link for a three-box order, write down which reference they will read.

After a delivery is validated, Odoo can still cancel the carrier request with Cancel next to Carrier Tracking Ref, then Send to shipper again after the carrier is changed. That issues a new tracking number and a new label. Train the cancel path before peak week. A label bought against the wrong account is a charge, and the documented recovery is cancel, then send again.

On the Business Central side, the parallel failures are clerical. The tracking number never gets typed, so Track Package has nothing to open. The item charge is assigned before Net Weight is filled, so By Weight is meaningless. The charge is posted after the sale and Adjust Cost - Item Entries does not run, so margin stays too high until someone notices. Standard-cost items throw the difference to purchase variance, and a report that only reads unit cost never shows the freight.

The label that prints before the customer is invoiced is the cash-flow version of the same gap. Odoo can charge the carrier account in production before the customer invoice exists. Business Central can hold a tracking number on a posted shipment while the freight-out charge waits for a later invoice. In both products, name the day you expect the freight dollars to exist on the order, and test that day with a real carrier response.

What to put in the first phase

Buy the label path and the freight path together. A first phase that only prints a PDF leaves the month-end freight bill where it is now. A first phase that only adds an item charge, while the bench still re-keys tracking numbers from a carrier tab, will be abandoned the first busy Friday.

For Odoo, the phase is concrete. Clean warehouse address and phone against the carrier file. Fill product weights. Choose Get Rate, or Get Rate and Create Shipment, per delivery method. Decide estimated cost versus the manual real-cost edit, and name who edits Unit Price before confirm. If more than one US carrier must be rated on the same package, configure EasyPost and decide wallet versus bring-your-own. If a tool outside Odoo will call Odoo, price the Custom plan and the External API. If LTL and parcel must share one rate shop, that tool is its own scope, with a written map back to the delivery product.

For Business Central, the phase is the agent, the services and their shipping times, the rule for who types Package Tracking No., and the item-charge routine. Choose Equally, By Amount, By Weight, or By Volume, and back the choice with Net Weight or Unit Volume where the suggestion needs it. Schedule Adjust Cost - Item Entries for charges that arrive after the sale. If a demo includes rate shopping, the extension or external system is a line item with credentials, a test mode, and an owner for the code.

Ask bidders for these artifacts before you compare hours.

  1. A list of carriers and services in phase one, and which ones are out of phase.
  2. The field that stores the tracking number, and whether a person or an interface fills it.
  3. The document where freight lands, and the batch job or manual edit that runs when the carrier bill is late.
  4. A test script: wrong ZIP, missing weight, test versus production, cancel and reship, one label per package, standard-cost variance or a zero-price delivery line edited to the real cost.
  5. Code ownership: who can change the connector when a carrier retires an API, and where the source lives.

Our target for a first usable phase is 8 to 12 weeks, on a scope limited to the carriers, weights, packages, and freight posting you can test on your own orders. Judge the bid by named people, hours, references, a phase plan, and that code ownership. Supply chain implementation is how we phase the operational workflows. The logistics page above is where the shipping desk, the warehouse, and the freight bill are one project.

If you have one parcel carrier, complete weights, and someone who will type a tracking number, start with Business Central's agent and item charges, or with one Odoo delivery method on Get Rate and Create Shipment. If you compare carriers on every carton, put EasyPost or another documented multi-carrier path in the test script and watch a production label get charged and then cancelled. If parcel and LTL share the bench, budget a connected rate shop and a posting design, and keep the vendor's discount claims out of the business case. Bring the carrier list and a sample of last month's freight bills to the call. We will match them to a phase.

How Flectic can help

Flectic connects your warehouse, transport, billing and finance on Dynamics 365 or Odoo for logistics operators of 20 to 100 people in the US and Canada, so freight costs tie to each load and each invoice. Flectic sends a written proposal with a fixed price for each phase before work starts. See the logistics and supply chain service for the carrier, 3PL billing and track-and-trace scope. Book a free discovery call with Flectic to decide where your shipping flow starts.

Sources

How to Set Up Shipping Agents - Business Central, Microsoft, October 2026

Track packages - Business Central, Microsoft, October 2026

Use item charges to account for extra trade costs, Microsoft, October 2026

Dynamics 365 Business Central pricing (United States), Microsoft, October 2026

Third-party shipping carriers, Odoo 19.0, Odoo, October 2026

Print shipping labels, Odoo 19.0, Odoo, October 2026

Shipping cost invoicing, Odoo 19.0, Odoo, October 2026

EasyPost integration, Odoo 19.0, Odoo, October 2026

How to cancel a shipping request to a shipper?, Odoo 19.0, Odoo, October 2026

Odoo Pricing, Odoo, October 2026

Odoo Success Packs, Odoo, October 2026

EasyPost pricing, EasyPost, October 2026

ShipStation rate comparison, ShipStation, October 2026

Frequently asked questions

Does Business Central print labels and shop rates, or do I still type the tracking number in after the carrier site?

Microsoft's shipping agent and package tracking pages cover agent codes, a service time on the sales line, a package number you enter, and a link that opens the carrier site. Rate shopping and label purchase sit outside those pages. If a demo shows live carrier rates inside Business Central, ask which extension or connected product is calling the carrier, and who owns that code.

Should I assign freight equally, by amount, by weight, or by volume?

Use By Weight when the carrier bill follows pounds and every item has Net Weight filled in. Use By Volume when cubes drive the charge and Unit Volume is filled in. Use By Amount when the fee should follow selling price. Use Equally only for a flat fee you intend to spread without using size or price. If Net Weight is blank, By Weight has nothing reliable to calculate, so fill the item card before you rely on that suggestion.

What happens to margin if the carrier invoice shows up after the goods are already sold?

In Business Central, cost of goods sold does not update by itself when an item charge posts after the sale. Run Adjust Cost - Item Entries so the extra cost moves to the outbound entries. On standard-cost items the charge does not change the unit cost, and the difference posts as a purchase variance. In Odoo, the documented real-cost path is a manual edit of the delivery product's unit price on the draft invoice before you confirm it.

Why is Odoo's shipping estimate different from the carrier's own price?

Get Rate builds cost from order weight, or from the sum of product weights, and from the distance between the warehouse address and the customer. A missing weight or a warehouse address the carrier does not recognize will skew or block that call. When the numbers still disagree, compare a shipment created on the carrier site, the Odoo estimate, and the debug log. Odoo documents a case where the request said six kilograms and the FedEx response said seven, and treats that as a carrier-side mismatch.

Will test mode charge my UPS or FedEx account?

Odoo warns that switching a delivery method from the test environment to production creates real labels and can charge the carrier account before the customer is billed. On the EasyPost connector, test labels are cancelled immediately and production labels are charged. Keep the method in test until the label is one you meant to buy, and expect a carrier charge once someone flips it to production.

If ShipStation calls into Odoo, is that the External API and therefore the Custom plan?

Calls that Odoo starts to carriers such as UPS, FedEx, and DHL are part of the Standard plan, not the External API. The External API is Custom plan only, and it is the case where outside software calls Odoo's JSON-RPC or XML-RPC API. A shipping tool that pushes orders and tracking into Odoo is that second case, so budget Custom. Confirm the direction of the calls before you pick the plan. Ask ShipStation for its current subscription and keep that fee on its own line, separate from the Odoo plan.

Is EasyPost enough for US parcels and LTL, or do I still need a separate rate shop?

EasyPost inside Odoo is the documented way to rate UPS, USPS, FedEx, DHL, and other carriers enabled on the EasyPost account, by package size and weight, and to print the label. A direct UPS, FedEx, or USPS delivery method talks to that one carrier. ShipStation's site claims a rate shop across 200+ parcel carriers and 50+ LTL carriers in one workflow. Use that connect path when parcel and LTL share a bench, and still map the chosen cost back to the order yourself.