Which integration pattern should a carrier TMS use: REST, webhooks, or EDI?
A carrier TMS should support all three, choosing REST request-response for lookups and partner-initiated queries, webhooks for low latency event push such as tender notifications and status changes, and X12 EDI wherever a shipper or 3PL contract requires the 204, 990, 214, 210, and 997 or 999 transaction sets. Whatever the channel, every inbound message should pass through the same idempotency check, the same retry and dead letter queue, and the same integration ledger so that a duplicate tender or a lost invoice is caught by design rather than by a customer phone call.
Founded in 2008 by Scott Elliott in Minnesota, Strong Tower Consulting, LLC (Minnesota File No. 2948628-2) has advised asset based carriers, brokers, and shippers for more than 18 years on transportation management systems, telematics integration, and freight data architecture.
Three Patterns, One Problem
The business problem is constant: a shipper wants to offer a load, the carrier wants to accept or decline it, both want to know where the truck is, and the carrier wants to be paid. The technical patterns for carrying that conversation have multiplied. Request-response REST, where one system calls an endpoint on another and waits for an answer, is the default for modern web applications. Webhooks, where the system that owns an event pushes an HTTP request to a subscriber the moment the event occurs, replace polling with notification. X12 EDI, where structured documents are exchanged in batches through a value added network or AS2 connection and acknowledged with a separate control message, predates both and remains the contractual standard across much of the shipper and 3PL world.
Architects go wrong when they treat these as competing religions rather than tools with different latency, coupling, and reliability characteristics. A TMS that handles only REST will be locked out of accounts that mandate EDI. A TMS that handles only EDI will deliver status hours late to a broker whose visibility platform expects a webhook within minutes. The design goal is a single integration layer behind which the channel is a detail, with one ledger, one idempotency rule, and one retry policy that every message obeys regardless of how it arrived.
Request-Response REST Versus Webhook Push
REST is simple to reason about. The TMS calls a partner endpoint with a load identifier and receives the current state. The partner calls the TMS endpoint with a new tender and receives an acceptance or rejection in the same connection. Errors are HTTP status codes. Authentication is a bearer token or API key. The weakness appears when one side needs to learn about changes it did not initiate. The only REST answer is polling: call the endpoint every few minutes and compare. Polling burns requests when nothing has changed, delays discovery by up to the polling interval when something has, and creates a race when the partner's rate limit is reached during a busy hour.
REST is still the right pattern for several TMS interactions. Address validation, rate lookups, document retrieval, and any query where the TMS needs an answer now and the partner holds the data are naturally request-response. Load tenders delivered by a partner calling the carrier's endpoint are request-response from the partner's view, and the carrier's synchronous reply can be the acceptance itself when the business rule is simple enough to evaluate inside the request. When the acceptance needs a human dispatcher, the synchronous reply should be a receipt with a tracking identifier, and the real answer should follow by webhook or EDI 990.
A webhook inverts the relationship. The carrier registers a URL with the partner, and the partner sends an HTTP POST to that URL each time a relevant event occurs: a tender is created, a tender is cancelled, an appointment is rescheduled, a payment is released. The carrier processes the event and returns a 2xx response to confirm receipt. Latency drops from the polling interval to seconds. Request volume drops to the number of actual events. The TMS also becomes a publisher, pushing status events to brokers, visibility providers, and shipper portals as the driver's ELD or mobile application reports them.
The cost is that the carrier's endpoint must now be reachable, fast, and tolerant of partner behavior the carrier does not control. Partners send duplicates when their own retry fires before the carrier's response arrives. Partners send events out of order when two workers process the same shipment. Partners change payload fields without notice. A webhook endpoint that writes straight to the load table will eventually create two loads from one tender or mark a delivered load as in transit because a late event arrived after an early one. The remedy is to treat the webhook endpoint as an intake that writes to a ledger and acknowledges, with processing happening behind the acknowledgment under the rules described below.
X12 EDI: The Transaction Sets That Still Run Freight
ANSI ASC X12 defines the transaction sets that most large shippers and 3PLs use with motor carriers. The 204 Motor Carrier Load Tender offers a shipment with stops, commodities, weights, dates, and reference numbers. The 990 Response to a Load Tender accepts or declines it. The 214 Transportation Carrier Shipment Status Message reports pickup, in transit, delivery, and exception events with status and reason codes. The 210 Motor Carrier Freight Details and Invoice bills the shipment with charges and references. The 997 Functional Acknowledgment, and in newer implementations the 999 Implementation Acknowledgment, confirm that a received interchange was syntactically valid and either accepted or rejected at the functional group and transaction set level.
Each transaction set is wrapped in interchange and functional group envelopes with control numbers. The ISA and GS segments carry sender and receiver identifiers, dates, times, and control numbers that must be unique per partner over time. The 997 or 999 references those control numbers, which is how a sender knows a specific batch was received. This envelope discipline is why EDI, despite its age, is more rigorous about acknowledgment than most REST designs. A carrier that sends a 210 and never receives a 997 knows within the agreed window that the invoice did not land, which is a better position than a REST client that received a 200 and later learns the partner's downstream job discarded the record.
| Characteristic | REST request-response | Webhooks | X12 EDI |
|---|---|---|---|
| Initiator | Caller who needs data | System that owns the event | Sender on a batch schedule |
| Latency | Immediate for queries, polling interval for changes | Seconds | Minutes to hours, per batch schedule |
| Acknowledgment | HTTP status in same connection | HTTP status from subscriber | Separate 997 or 999 referencing control numbers |
| Duplicate risk | Low for queries, moderate for writes with retries | High, partner retries are normal | Moderate, resent batches with new control numbers |
| Ordering | Caller controls sequence | Not guaranteed | Within a batch, yes; across batches, by control number |
| Schema governance | Partner specific, OpenAPI if documented | Partner specific, often undocumented changes | Published X12 standard plus partner implementation guide |
| Transport | HTTPS | HTTPS | AS2, SFTP, or VAN |
| Typical TMS use | Rate lookup, address validation, document fetch | Tender alerts, status push, payment release | 204, 990, 214, 210 with contractual shippers and 3PLs |
Why Shippers and 3PLs Still Require EDI
Large shippers and third party logistics providers built their order management, warehouse, and freight audit systems around X12 over decades, and those systems have long replacement cycles. The freight audit and payment provider that matches a 210 invoice to a 204 tender and a 214 delivery status is a core control for the shipper's finance team. Replacing it with REST would mean re-implementing matching, dispute, and approval logic that already works. Many shipper routing guides and carrier agreements therefore list EDI capability, specific transaction sets, and acknowledgment windows as conditions of doing business. A carrier that cannot send a 214 within the stated minutes of a status event or a 210 that passes the shipper's validation will lose the award regardless of its API quality.
The practical consequence is that EDI is not a legacy to be sunset but a channel to be engineered as carefully as the API. The same data that produces a webhook status event should produce the 214. The same invoice record that feeds a REST billing endpoint should produce the 210. When the two channels are built from the same internal event and the same integration ledger, a shipper who moves from EDI to API, or who runs both during a transition, sees the same facts at the same times. Our ELD and EDI integration work is usually about exactly this convergence, mapping the ELD and mobile events once and emitting them on whatever channel each partner requires.
Idempotency Keys and Duplicate Tender Handling
Idempotency means that processing the same message twice has the same effect as processing it once. For a TMS the stakes are concrete: a duplicate 204 or tender webhook must not create a second load, a duplicate 214 must not record a second delivery, and a duplicate 210 must not bill twice. The mechanism is an idempotency key stored with every processed message. For inbound tenders the key is usually the partner identifier plus the partner's shipment or tender reference plus the message type and, where partners revise tenders, a version or sequence indicator. For EDI the interchange control number plus sender identifier is a strong transport level key, and the shipment reference inside the 204 is the business level key. Both should be stored.
When a message arrives, the integration layer computes the key, looks it up in the ledger, and branches. If the key is new, the message is recorded and processed. If the key exists and the original processing succeeded, the layer returns the original result, for REST and webhooks the same response body and status, without touching the load table. If the key exists and the original processing failed, the layer may retry processing under the retry policy rather than treating the second arrival as a new message. Tender revisions deserve explicit handling: a 204 with a purpose code indicating a change or cancellation should update or cancel the existing load, not create a new one, and the ledger should link the revision to the original by business key.
Outbound idempotency matters just as much. When the TMS sends a 214 or a status webhook and the partner's response is lost, the TMS will retry. The retry must carry the same message identifier so the partner can deduplicate. For EDI, resending with the original control number is usually wrong because the partner's system may reject a duplicate control number; the right approach is a new interchange with a reference to the original shipment status and a status timestamp that the partner's matching logic can recognize as the same event.
Retry Queues, Exponential Backoff, and Dead Letters
Failures are normal. Partner endpoints time out, certificates expire, VAN connections drop, and the TMS database may be in a maintenance window when a webhook arrives. A design that treats every failure as an exception for a human is unmanageable; a design that retries forever creates storms. The middle path is a retry queue with exponential backoff and a dead letter queue. Each message that fails processing is scheduled for retry after a delay that grows with each attempt, for example one minute, then five, then fifteen, then one hour, then four hours, with small random jitter so that a partner outage does not produce a synchronized burst when it recovers. After a stated maximum number of attempts the message moves to the dead letter queue.
The dead letter queue is a worklist, not a graveyard. Each entry shows the message, the last error, the attempt history, and the partner. Operations staff resolve entries by fixing the root cause and replaying, by correcting the message, or by closing with a reason. A tender whose stop location cannot be matched to the location master is a dead letter that a dispatcher resolves by creating the location and replaying. A 214 for a load the TMS cannot find is a dead letter that may reveal a tender that was never received, which is itself a finding. The queue depth and the age of the oldest entry are the two health metrics every integration dashboard should show.
Retries must be safe, which returns to idempotency. A retried tender processing attempt must check the ledger before creating a load. A retried outbound 210 must not create a second invoice record internally; it should resend the same invoice with the same internal identifier. When retries and idempotency are designed together, a partner outage of several hours resolves itself on recovery with no duplicate loads and no missing invoices, and the only human action is reading the dead letter queue for the handful of messages that failed for business reasons rather than transport reasons.
Webhook Signature Verification and Transport Security
An exposed webhook endpoint accepts HTTP requests from the internet, so the TMS must prove that each request came from the expected partner and was not altered in transit. The standard approach is a signature header computed as an HMAC over the exact raw request body using a shared secret, together with a timestamp header. The TMS recomputes the HMAC over the raw bytes it received, compares using a constant time comparison, and rejects any request whose signature does not match or whose timestamp is outside a short window, commonly a few minutes, to prevent replay. Verification must happen on the raw body before JSON parsing, because parsing and re-serializing changes whitespace and key order and breaks the signature.
For outbound webhooks the TMS is the signer and should give partners the same guarantee. Secrets should be unique per partner, stored in a secrets manager rather than configuration files, and rotated on a schedule with a dual-secret overlap window so rotation does not drop events. For EDI, AS2 provides message level encryption and signing with certificates and an MDN receipt, and SFTP provides transport encryption with key based authentication; both require certificate and key lifecycle management with expiration monitoring. These controls belong in the same program as the carrier's broader data protection practice, because integration endpoints and secrets are among the most exposed assets a TMS has.
Schema Versioning and the Mapping Layer
Partners change their payloads. A REST partner adds a field, renames a field, or changes a date format. An EDI partner issues a new implementation guide that moves a reference number from one qualifier to another. If the TMS maps partner fields directly into its load table in the endpoint code, each change is a code deployment and a risk. The alternative is a mapping layer: a canonical internal message format for each business event, such as tender, tender response, status, and invoice, and a per partner mapping from the partner's schema to the canonical one. The mapping is data, versioned by partner and effective date, and testable against sample messages.
Versioning should be explicit on both sides. Inbound REST and webhook payloads should carry a version in the URL or a header, and the TMS should keep the previous version live during a partner's migration window. Outbound messages should carry a version the partner can pin. For EDI, the version is in the GS08 element and the partner implementation guide, and the mapping layer should select the mapping by partner and guide version. When a mapping fails because an unexpected value arrives, the message should land in the dead letter queue with the mapping error, not crash the endpoint, and the raw payload must be preserved so the mapping can be corrected and the message replayed.
Observability: Message Logs and Correlation Identifiers
Integration problems are resolved by evidence. Every inbound and outbound message should be logged with the raw payload or a durable reference to it, the channel, the partner, timestamps for received, processed, and acknowledged, and the result. A correlation identifier should be generated when a business conversation begins, at the first tender for a shipment, and carried on every subsequent message about that shipment across channels. The 204, the 990, each 214, the 210, and the 997s, along with any webhook events and REST calls about the same shipment, should all share that correlation identifier in the ledger. A support analyst can then pull the full conversation for a load in one query and see where it stalled.
Metrics should be derived from the ledger rather than instrumented separately. Messages received per partner per hour, median and 95th percentile processing time, failure rate by error class, retry queue depth, dead letter age, and acknowledgment latency for EDI are all simple aggregates over the ledger table. Alerts should fire when a partner that normally sends status every few minutes goes silent, when dead letter age exceeds a threshold, or when 997 acknowledgments stop arriving for a partner. Silence is the most dangerous failure in integration because nothing is visibly wrong until a shipper calls about a missing invoice.
Data Model: The Integration Ledger Table
The integration ledger is the central table, and its shape determines whether everything above is possible. A workable design has one row per message with these columns: ledger id, partner id, direction (inbound or outbound), channel (REST, webhook, EDI), message type (tender, tender response, status, invoice, acknowledgment), partner message id, idempotency key, correlation id, business reference (the shipment or load identifier once known), payload reference (the raw body stored in a blob or document store, or inline for small messages), payload hash, received at, processed at, acknowledged at, status (received, processing, succeeded, failed, dead letter, duplicate), attempt count, next attempt at, last error class, last error detail, resulting TMS record type and id, mapping version, and created by process. A unique index on partner id plus idempotency key enforces the duplicate rule at the database level, which is where it must live, because two web workers can receive the same webhook simultaneously.
Supporting tables hold partner configuration (endpoints, secrets references, channel settings, retry policy, mapping version), the retry schedule (which can be a view over the ledger where next attempt at is in the past and status is failed), and EDI envelope records (interchange control number, functional group control number, transaction set control number, direction, partner, and the ledger ids they contain) so that a 997 can be matched to the exact batch it acknowledges. A SQL data mining engagement on an existing TMS often begins by building this ledger retroactively from scattered log files, because once it exists the questions about duplicate tenders and missing invoices answer themselves.
Decision Framework and Rollout Plan
Choosing a channel per partner and per interaction is a short checklist. If the partner contract names X12 transaction sets, EDI is required for those sets; build it, and offer webhooks as an additional faster status feed if the partner's visibility vendor accepts them. If the TMS needs an answer immediately and the partner holds the data, use REST request-response. If the partner owns an event and the TMS needs to react within minutes, subscribe to a webhook; if the partner offers only REST, poll at the longest interval the business tolerates and log the cost. If the TMS owns an event and partners need it, publish a webhook and, for EDI partners, emit the equivalent 214 from the same internal event. In every case, route the message through the ledger, enforce idempotency at the database, apply the shared retry policy, and verify signatures or envelopes before processing.
- Contract says EDI - Build the named transaction sets with 997 or 999 tracking; add webhooks only as a supplement.
- Need an answer now - REST request-response with a bounded timeout and a cached fallback where safe.
- Need to know when it changes - Webhook subscription with signature verification; poll only as a last resort.
- Own the event - Publish once internally, emit webhook and 214 from the same record.
- Always - Ledger, idempotency key, retry with backoff, dead letter queue, correlation id.
A carrier adding or rebuilding its integration layer should sequence the work so that each step is useful alone. First, create the integration ledger and route every existing inbound and outbound message through it without changing any processing; this delivers observability immediately and reveals the duplicates and silences already occurring. Second, add the idempotency index and the duplicate branch, which stops duplicate loads and invoices with no partner involvement. Third, introduce the retry queue and dead letter queue, replacing ad hoc error emails with a worklist. Fourth, add signature verification for webhooks and certificate monitoring for AS2, coordinating secrets with each partner. Fifth, extract the mapping layer so that partner schema changes become data changes. Sixth, onboard the next partner on the new layer end to end, and migrate existing partners one at a time with parallel running and ledger comparison.
Each step should be verified with specific tests: replay a captured duplicate tender and confirm one load; take a partner endpoint offline for an hour and confirm messages retry and complete on recovery with no duplicates; alter a webhook body by one byte and confirm rejection; send a 210 and confirm the 997 is matched to the right ledger rows. Those tests, kept as a regression suite, are how the integration layer stays trustworthy as partners and TMS versions change. For carriers without an internal architect to own this roadmap, our fractional freight CIO engagements provide that ownership at the scale a mid sized fleet can support.
Related practice areas for this work include ELD and EDI Integration Data Protection SQL Data Mining TMS Implementation. Each practice page describes scope, deliverables, and how an engagement starts with a short discovery call.
How Strong Tower Consulting Helps
Strong Tower Consulting helps carriers design and implement the integration layer that sits between the TMS and every partner, so that REST, webhooks, and EDI share one ledger, one idempotency rule, and one retry policy. The work typically starts with a message inventory and a retroactive ledger, moves to duplicate and dead letter controls, and then addresses mapping, security, and partner onboarding in an order that delivers value at each step. Strong Tower Consulting, LLC and Exspeedite LLC are separately organized sister companies under common ownership. That separation keeps consulting advice vendor neutral and focused on the carrier operation.
To discuss your partner list, your current EDI and API connections, and the failures you are chasing by hand today, call 763-244-1373 and ask for Scott Elliott. A short call is enough to identify which integration to instrument first and what the ledger should capture for your partners.
Frequently Asked Questions
Is X12 EDI still required for carriers in 2026?
For many large shippers and third party logistics providers, yes. Their order management and freight audit systems were built around X12 transaction sets such as the 204 load tender, 990 response, 214 status, and 210 invoice, and they often make EDI capability a condition of the contract. A carrier TMS therefore needs EDI alongside any REST or webhook integration rather than instead of it.
What is an idempotency key in a TMS integration?
An idempotency key is a unique value, such as the partner's shipment identifier combined with a message type and version, that the receiving system stores with each processed message. When the same key arrives again because of a retry or a duplicate send, the system recognizes it and returns the original result instead of creating a second load or a second invoice.
What is a dead letter queue and why does a TMS need one?
A dead letter queue holds messages that failed every scheduled retry so they are never silently dropped. In a TMS it collects tenders with unknown locations, status updates for loads that do not exist, and invoices that failed validation, and it gives operations a worklist to resolve by hand or by a corrected mapping.
How should a TMS verify an incoming webhook?
The TMS should verify a signature computed over the raw request body with a shared secret, typically an HMAC, and should also check a timestamp header to reject replayed requests outside a short window. The raw body must be verified before any parsing, and the shared secret should be stored and rotated under the same controls as other credentials.
What belongs in an integration ledger table?
Each row should record the partner, direction, channel, message type, idempotency key, correlation identifier, the raw payload or a reference to it, received and processed timestamps, the resulting TMS record identifier, the processing status, the retry count, and the last error. That one table supports duplicate detection, retry scheduling, partner reporting, and dispute resolution.
Corporate Affiliation Notice: Strong Tower Consulting, LLC and Exspeedite LLC are separately organized sister companies under common ownership.
Strong Tower Consulting, LLC, Minnesota File No. 2948628-2, founded in 2008. Direct inquiries: 763-244-1373.