<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: soap</title>
    <description>The latest articles on DEV Community by soap (@soap).</description>
    <link>https://dev.to/soap</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3834420%2F19305c21-9f66-471f-82b0-fa5946cdfb26.png</url>
      <title>DEV Community: soap</title>
      <link>https://dev.to/soap</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/soap"/>
    <language>en</language>
    <item>
      <title>Migrating to freightutils-mcp v2.0.0: snake_case across every surface</title>
      <dc:creator>soap</dc:creator>
      <pubDate>Wed, 29 Apr 2026 14:55:01 +0000</pubDate>
      <link>https://dev.to/soap/migrating-to-freightutils-mcp-v200-snakecase-across-every-surface-4nkk</link>
      <guid>https://dev.to/soap/migrating-to-freightutils-mcp-v200-snakecase-across-every-surface-4nkk</guid>
      <description>&lt;p&gt;I shipped v2.0.0 of freightutils-mcp on 25 April. It's a breaking change with one purpose: one canonical input schema across the npm package, the n8n node, the Zapier app, and the HTTP MCP endpoint at freightutils.com/api/mcp.&lt;/p&gt;

&lt;p&gt;If you're integrating against any of these, here's what you need to know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why snake_case
&lt;/h2&gt;

&lt;p&gt;Response keys were already snake_case across the REST API. Input keys were polyglot — some camelCase, some snake_case, depending on which surface you hit. That asymmetry is fine when you're building one integration. It rots when you maintain four.&lt;/p&gt;

&lt;p&gt;The fix is one canonical schema. Inputs and outputs both snake_case, across every surface. Agents you build against the npm package work identically against the HTTP MCP endpoint. n8n workflows port to Zapier with field-name parity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed: 13 keys, 3 tools
&lt;/h2&gt;

&lt;p&gt;Every other tool (cbm, ldm, chargeable_weight, the ADR family, airline, container, hs_code, incoterms, unlocode, uld, vehicle, pallet_fitting, unit_converter) was already snake-clean in v1.x. Only three tools had camelCase inputs:&lt;/p&gt;

&lt;h3&gt;
  
  
  uk_duty_calculator
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Old&lt;/th&gt;
&lt;th&gt;New&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;commodityCode&lt;/td&gt;
&lt;td&gt;commodity_code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;originCountry&lt;/td&gt;
&lt;td&gt;origin_country&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;customsValue&lt;/td&gt;
&lt;td&gt;customs_value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;freightCost&lt;/td&gt;
&lt;td&gt;freight_cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;insuranceCost&lt;/td&gt;
&lt;td&gt;insurance_cost&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  consignment_calculator (items[] fields)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Old&lt;/th&gt;
&lt;th&gt;New&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;grossWeight&lt;/td&gt;
&lt;td&gt;gross_weight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;palletType&lt;/td&gt;
&lt;td&gt;pallet_type&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  shipment_summary
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Old&lt;/th&gt;
&lt;th&gt;New&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;freightCost&lt;/td&gt;
&lt;td&gt;freight_cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;insuranceCost&lt;/td&gt;
&lt;td&gt;insurance_cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;items[].palletType&lt;/td&gt;
&lt;td&gt;items[].pallet_type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;items[].hsCode&lt;/td&gt;
&lt;td&gt;items[].hs_code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;items[].unNumber&lt;/td&gt;
&lt;td&gt;items[].un_number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;items[].customsValue&lt;/td&gt;
&lt;td&gt;items[].customs_value&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to migrate
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using the npm package
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;freightutils-mcp@2.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update any agent or script calling the three affected tools. If you use TypeScript, the types now require snake_case — TS will tell you which call sites to fix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the HTTP MCP endpoint
&lt;/h3&gt;

&lt;p&gt;No install step. Update your tools/call arguments to snake_case for the three affected tools. Endpoint: &lt;a href="https://www.freightutils.com/api/mcp" rel="noopener noreferrer"&gt;https://www.freightutils.com/api/mcp&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using n8n
&lt;/h3&gt;

&lt;p&gt;Update to &lt;a href="mailto:n8n-nodes-freightutils@0.2.0"&gt;n8n-nodes-freightutils@0.2.0&lt;/a&gt;. Fields renamed in the workflow UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Consignment item: grossWeight → gross_weight&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duty Calculator: commodityCode / originCountry / customsValue&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ULD / Container / Vehicle lookup: *Type / *Category → snake_case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convert: from → from_unit, to → to_unit&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using Zapier
&lt;/h3&gt;

&lt;p&gt;Update to v0.2.0. Renamed user-input fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Consignment: grossWeight → gross_weight&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UK Duty: commodityCode / originCountry / customsValue&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Action-level keys ukDuty, chargeableWeight) are kept as-is to avoid breaking existing Zaps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for agent builders
&lt;/h2&gt;

&lt;p&gt;If you're building an agent that needs landed-cost reasoning or shipment summary calculation, you can now write one schema-aware prompt and deploy through whichever channel fits the user. Same field names, same response shape, same canonical answer.&lt;/p&gt;

&lt;p&gt;That's the whole point of the migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;npm: &lt;a href="https://www.npmjs.com/package/freightutils-mcp" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/freightutils-mcp&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitHub: &lt;a href="https://github.com/SoapyRED/freightutils-mcp" rel="noopener noreferrer"&gt;https://github.com/SoapyRED/freightutils-mcp&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release: &lt;a href="https://github.com/SoapyRED/freightutils-mcp/releases/tag/v2.0.0" rel="noopener noreferrer"&gt;https://github.com/SoapyRED/freightutils-mcp/releases/tag/v2.0.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP MCP: &lt;a href="https://www.freightutils.com/api/mcp" rel="noopener noreferrer"&gt;https://www.freightutils.com/api/mcp&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;n8n node: &lt;a href="https://www.npmjs.com/package/n8n-nodes-freightutils" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/n8n-nodes-freightutils&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Free tier: 25 req/day anon, 100/day with key. Pro: 50K/mo at £19.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you hit anything weird in the migration, GitHub issues on the repo are the fastest path to a fix.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>api</category>
      <category>freight</category>
    </item>
    <item>
      <title>How loading metres (LDM) actually work in European groupage freight — with pricing examples</title>
      <dc:creator>soap</dc:creator>
      <pubDate>Tue, 14 Apr 2026 03:40:35 +0000</pubDate>
      <link>https://dev.to/soap/how-loading-metres-ldm-actually-work-in-european-groupage-freight-with-pricing-examples-4gid</link>
      <guid>https://dev.to/soap/how-loading-metres-ldm-actually-work-in-european-groupage-freight-with-pricing-examples-4gid</guid>
      <description>&lt;p&gt;If you've ever shipped pallets across Europe, you've been quoted in loading metres. But most explanations online skip the part that actually matters — how LDM affects your freight cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  The formula
&lt;/h2&gt;

&lt;p&gt;LDM = (Length × Width × Quantity) ÷ 2.4&lt;/p&gt;

&lt;p&gt;Where 2.4m is the standard European trailer width (EN 283). One loading metre = a 1m strip of trailer floor, full width.&lt;/p&gt;

&lt;p&gt;A single Euro pallet (1200 × 800mm): 0.4 LDM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for pricing
&lt;/h2&gt;

&lt;p&gt;European groupage carriers quote per-LDM. A typical UK→Germany lane might be £35-45 per LDM. So 8 Euro pallets = 3.2 LDM = roughly £112-144 before surcharges.&lt;/p&gt;

&lt;p&gt;But here's what most calculators don't tell you: &lt;strong&gt;stackability halves your cost.&lt;/strong&gt; If those 8 pallets are stackable (factor 2), your LDM drops to 1.6 = £56-72. However, your weight-per-LDM jumps to 2,000 kg/LDM, which may trigger a weight surcharge.&lt;/p&gt;

&lt;p&gt;Both space AND weight must be considered together.&lt;/p&gt;

&lt;h2&gt;
  
  
  The free tool
&lt;/h2&gt;

&lt;p&gt;I built a free LDM calculator at &lt;a href="https://www.freightutils.com/ldm" rel="noopener noreferrer"&gt;freightutils.com/ldm&lt;/a&gt; that handles all of this — Euro/UK/US pallets, stackability, weight checks, and 6 vehicle types including US 53ft trailers.&lt;/p&gt;

&lt;p&gt;It's also available as a free REST API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://www.freightutils.com/api/ldm?pallet=euro&amp;amp;qty=8&amp;amp;stackable=true&amp;amp;weight=400"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No auth, no signup. JSON response with LDM, utilisation %, pallet spaces, and weight warnings.&lt;/p&gt;

&lt;p&gt;Full API docs: &lt;a href="https://www.freightutils.com/api-docs" rel="noopener noreferrer"&gt;freightutils.com/api-docs&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by a freight transport planner working night shifts at Heathrow. If you're building freight software and need reliable calculations, the entire API is free and open.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>freight</category>
      <category>logistics</category>
      <category>api</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Built a free REST API for ADR dangerous goods data — 2,939 entries, no auth, JSON responses</title>
      <dc:creator>soap</dc:creator>
      <pubDate>Fri, 20 Mar 2026 00:04:26 +0000</pubDate>
      <link>https://dev.to/soap/built-a-free-rest-api-for-adr-dangerous-goods-data-2939-entries-no-auth-json-responses-5g07</link>
      <guid>https://dev.to/soap/built-a-free-rest-api-for-adr-dangerous-goods-data-2939-entries-no-auth-json-responses-5g07</guid>
      <description>&lt;p&gt;I built FreightUtils — a set of free freight calculation &lt;br&gt;
tools where every tool has a public REST API. No API key &lt;br&gt;
needed, CORS enabled, JSON responses.&lt;/p&gt;

&lt;p&gt;The main dataset is ADR 2025 (European dangerous goods &lt;br&gt;
regulations) with 2,939 entries including all variant rows, &lt;br&gt;
rebuilt from official UNECE source data.&lt;/p&gt;

&lt;p&gt;Endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET /api/adr?un=1203 — dangerous goods lookup by UN number&lt;/li&gt;
&lt;li&gt;GET /api/adr?q=petrol — search by name&lt;/li&gt;
&lt;li&gt;GET /api/ldm — loading metres calculator&lt;/li&gt;
&lt;li&gt;GET /api/cbm — cubic metres calculator&lt;/li&gt;
&lt;li&gt;GET /api/chargeable-weight — air freight weight comparison&lt;/li&gt;
&lt;li&gt;GET /api/pallet — pallet fitting calculator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full docs: &lt;a href="https://www.freightutils.com/api-docs" rel="noopener noreferrer"&gt;https://www.freightutils.com/api-docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built with Next.js on Vercel. Interested in feedback on the &lt;br&gt;
API design — especially from anyone who works with logistics &lt;br&gt;
or freight software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freightutils.com" rel="noopener noreferrer"&gt;https://www.freightutils.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>nextjs</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
  </channel>
</rss>
