Webhook Integration Guide

Overview

The TAI TMS webhook system delivers HTTP POST notifications to your endpoint when events occur inside the platform — shipment lifecycle changes, customer and carrier record updates, and accounting document creation.

How It Works

Webhooks are configured through Source Settings in the TMS admin interface. Each webhook integration is an IntegrationSource of type PublicAPIWebhooks, scoped to one or more Linked Organizations. When a triggering event occurs for a record that belongs to a linked organization, the TMS serializes the relevant data and POSTs it as JSON to the URL(s) you have configured.

TMS Event Occurs
      │
      ▼
Linked Organization matches?
      │ Yes
      ▼
(Shipment events only) Batch in ~1-min window
      │
      ▼
Serialize payload (camelCase JSON)
      │
      ▼
POST to configured URL
      │
      ▼
Log result to WebhookActivityLog

Available Webhooks

CategoryWebhookTrigger
ShipmentShipmentCreateUrlNew shipment persisted
ShipmentDetailUpdateUrlAny shipment field or child record edited
ShipmentStatusUpdateUrlStatus change, stop-date edit, EDI 214, tracking updates
ShipmentLocationUpdateUrlGPS/location ping (15-min throttle)
AccountingBillCreateUrlCarrier/vendor bill approved (~5 second delay)
CommissionBillCreateUrlCommission approved to Created
InvoiceCreateUrlCustomer invoice created
InvoiceCreateWithShipmentUrlCustomer invoice created (includes shipment)
CustomerCustomerCreateUrlNew customer organization
CustomerUpdateUrlCustomer record edited (direct or indirect)
CarrierLSPCarrierCreateUrlNew broker carrier (Highway onboarding only)
LSPCarrierUpdateUrlBroker carrier record edited

Key Behaviors

BehaviorDetail
HTTP methodPOST
Content typeapplication/json
EncodingUTF-8
Property namingcamelCase
Date formatISO 8601 — yyyy-MM-ddTHH:mm:ssK (UTC)
Enum serializationString values (not integers)
Retry policyNo automatic retries — each event is attempted once
Delivery guaranteeAt-most-once. If your endpoint is unavailable or errors, the event is logged and no further delivery is attempted.
TransportHTTPS strongly recommended but not enforced; plain HTTP endpoints are accepted (see Authentication)
Custom headersNone. Only Authorization (if configured) plus HttpClient's auto-added Content-Type and Content-Length. No User-Agent, no X-Webhook-*, no HMAC signature.
HTTP redirects3xx responses are followed automatically

Shipment Webhook Batching

Shipment-related webhooks (ShipmentCreateUrl, ShipmentDetailUpdateUrl, ShipmentStatusUpdateUrl, ShipmentLocationUpdateUrl) are dispatched via a background queue with a ~1-minute delay after the triggering event. Multiple edits to the same shipment within that window coalesce into a single delivery — the timer resets on each new change and fires ~1 minute after the last change is saved. This prevents duplicate webhooks when users make multiple edits in quick succession.

Accounting, customer, and carrier webhooks are dispatched immediately, with one exception: BillCreateUrl uses a background job with a ~5-second delay.

Versioning

The Version source setting controls how shipment statuses are labeled in the payload. It applies only to shipment webhooks (Create, Detail, Status, Location). Accounting, customer, and carrier payloads are unversioned and always use the current schema.

VersionBehavior
2Statuses transformed: Committed → Booked and Quote → Quoted. All other statuses (Dispatched, InTransit, OutForDelivery, Delivered, etc.) unchanged.
3 (default)Current format. Statuses sent as-is: Committed and Quote.

If Version is missing, empty, or set to any value other than "2", the payload is sent in V3 form.

Source Setting Parameters

When configuring a Source Setting of type PublicAPIWebhooks, the following parameters are available:

ParameterTypeDescription
ShipmentCreateUrlURLEndpoint for shipment creation events.
ShipmentDetailUpdateUrlURLEndpoint for shipment detail update events. Also fires alongside ShipmentStatusUpdateUrl.
ShipmentStatusUpdateUrlURLEndpoint for shipment status and transit-related change events.
ShipmentLocationUpdateUrlURLEndpoint for location updates. 15-min throttle.
BillCreateUrlURLEndpoint for bill approval events. Fires with a ~5-second delay.
CommissionBillCreateUrlURLEndpoint for commission approval events.
InvoiceCreateUrlURLEndpoint for invoice creation events (invoice only).
InvoiceCreateWithShipmentUrlURLEndpoint for invoice creation events (invoice + shipment). Fires independently of InvoiceCreateUrl.
CustomerCreateUrlURLEndpoint for customer creation events.
CustomerUpdateUrlURLEndpoint for customer update events (includes indirect triggers).
LSPCarrierCreateUrlURLEndpoint for carrier creation events. Currently limited to Highway onboarding.
LSPCarrierUpdateUrlURLEndpoint for carrier update events.
AuthorizationStringStatic authorization token sent verbatim in the Authorization request header.
UserNameStringUsername for HTTP Basic Authentication (paired with Password).
PasswordStringPassword for HTTP Basic Authentication (paired with UserName).
VersionInteger (2 or 3)Controls shipment status label format. Defaults to 3.
DoNotMarkInvoiceAsPrintedBoolean (true/false)When true, invoices are not marked as printed after the webhook fires. Defaults to false.

Authentication

All webhook communication is outbound — the TMS sends requests to your endpoint. You are responsible for securing your endpoint; the TMS provides the following mechanisms to prove the request is coming from the platform.

Transport Security

The TMS supports TLS 1.0, 1.1, and 1.2. TLS 1.3 is not currently supported. If your endpoint enforces TLS 1.3-only, webhook delivery will fail at the transport layer.

HTTPS is strongly recommended but not enforced. The TMS will POST to a plain http:// URL if configured — this exposes the Authorization header and payload in transit.

Recommendation: Configure https:// endpoints only, and require TLS 1.2 on your endpoint.

Authentication Methods

Option 1 — Static Authorization Header

Set the Authorization source setting parameter to any string value. The TMS will include it verbatim as the Authorization header on every request. No prefix or transformation is added.

# Bearer token
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# Custom API key
Authorization: ApiKey abc123xyz

# HMAC signature (pre-computed and stored as a static value)
Authorization: HMAC sha256=abc123...

Option 2 — HTTP Basic Authentication

Set both the UserName and Password source setting parameters. The TMS will Base64-encode username:password (ASCII encoding) and attach it as a standard Authorization: Basic header.

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

When Both Are Configured

If both are set, Basic Authentication takes precedence. The effective header sent will be Authorization: Basic <base64(user:pass)>.

ConfigurationHeader sent
Authorization onlyAuthorization: <your value>
UserName + Password onlyAuthorization: Basic <base64(user:pass)>
Both setAuthorization: Basic <base64(user:pass)> (Basic wins)

Verifying Requests Are From the TMS

Because the TMS does not sign payloads with a cryptographic signature (no HMAC, no X-Signature header), the recommended approach is:

  1. Use a strong secret in the Authorization header. Treat the value as a shared secret — long, randomly generated, validated on every request.
  2. Accept requests only over HTTPS.
  3. Return 401 Unauthorized for missing or incorrect credentials. The TMS will log the response code but will not retry.

Error Handling & Logging

Delivery Behavior

The TMS makes a single attempt to deliver each webhook. There is no automatic retry.

ScenarioTMS behavior
Endpoint returns 2xxSuccess — response body and status code logged.
Endpoint returns 3xxFollows the redirect automatically to the new URL.
Endpoint returns 4xx or 5xxLogged as-is — the non-2xx status is recorded but does not trigger a retry or exception. Response body is still captured.
Network error / DNS failureException caught — error message logged, no response data captured.
Endpoint times outException caught — error message logged. Default HttpClient timeout (~100 seconds).
TLS / certificate errorException caught — error message logged.

Important: The TMS does not distinguish between 2xx and non-2xx responses for retry purposes. A 500 from your endpoint is logged just like a 200 — no re-delivery is attempted either way. To signal a real problem, you must proactively monitor WebhookActivityLogs yourself.

Your endpoint should respond quickly. Long-running processing should be dequeued asynchronously — accept the webhook, return 200 OK immediately, and process in the background.

Webhook Activity Logs

Every delivery attempt — successful or not — is written to the WebhookActivityLogs table in the TMS logging database, joined with ApiDetails via ApiDetailId.

FieldTypePopulatedDescription
WebhookActivityLogIdlongAlwaysAuto-incrementing primary key.
OrganizationIdintAlwaysThe organization that owns the triggering record.
StaffIdintAlways for user-initiated events; may reflect a system user ID for background/EDI/driver-tracking eventsStaff member whose action triggered the webhook.
IntegrationSourceIdint?Usually populated; nullable in schemaThe Source Setting that owns this webhook configuration.
WebhookTypeWebhookType? (nullable enum, 1–13)AlwaysWhich webhook fired. Serialized as an integer in SQL.
Idlong?AlwaysID of the triggering record — polymorphic per WebhookType.
StartDateTimedatetime (UTC)AlwaysWhen TMS began processing the webhook.
EndDateTimedatetime (UTC)AlwaysWhen the delivery attempt completed.
Durationint (seconds)AlwaysDATEDIFF(SECOND, StartDateTime, EndDateTime).
ErrorMessagestringNetwork-level error onlyException message. Truncated to 1,000 chars. Absent when any HTTP response was received.
ApiDetail.UrlstringWhen an HTTP request was sentAbsolute URL. Truncated to 200 chars.
ApiDetail.HttpStatusCodeintWhen an HTTP response was receivedResponse code (200, 401, 500, etc.).
ApiDetail.RequeststringAlwaysThe full JSON payload that was sent.
ApiDetail.ResponsestringWhen an HTTP response was receivedRaw response body (any status code).

Diagnosing Common Failures

Webhook fired, endpoint returned 401

  • ErrorMessage is null (an HTTP response was received).
  • ApiDetail.HttpStatusCode is 401.
  • Check that the Authorization (or Basic) value matches what your endpoint expects.

Webhook fired but nothing received

  • Empty ApiDetail.Response with HttpStatusCode 200 → your endpoint returned an empty body. Fine.
  • ErrorMessage populated → network-level failure before any HTTP response (DNS, timeout, TLS).

Webhook never appeared in logs

  • Confirm the triggering record's org matches the Source Setting's Linked Organizations.
  • For shipment webhooks, wait past the ~1-minute batching window.
  • For ShipmentLocationUpdateUrl, check the 15-minute throttle window hasn't suppressed it.
  • Log entries are batched (~10s delay before queryable) — see below.

Log Persistence and Batching

Webhook activity logs are flushed to the logging database in batches. A flush occurs when either:

ConditionThreshold
Time since last flush> 10 seconds
Items accumulated≥ 200 entries

Expect up to a ~10-second delay before a delivery attempt is queryable in the logs.


Did this page help you?