Skip to content
English
  • There are no suggestions because the search field is empty.

Public API and Webhooks Internals

How the Tai TMS public API and partner webhooks work: the versioned contract, retired v1 operations, authentication, webhook security, and rate limits.

This staff-only article explains how the Tai TMS exposes its public API and inbound partner webhooks: the versioned external contract, which older (v1) operations have been retired, how callers authenticate, how partner webhooks are secured (and where they are not), how requests are rate-limited at the edge, and how the contract is versioned over time.

Overview

The Tai TMS provides an external, customer-and-partner-facing API alongside the application that broker staff use. This public API is a deliberately separate surface from the internal endpoints the product's own screens use: it is a published, versioned contract that customers and integration partners build against. Version 2 ("v2") is organized into business areas: shipping (shipments, truckload quotes, alerts, assignments, documents, tracking updates, and reference numbers), brokers, customers, carriers (LSP carriers and their trailers), invoices, bills, invoice and bill payments, commissions, shipment commissions, sales reps, staff, organizations (including custom shipment reference types), load boards, shipment locations, shipment stops, general-ledger accounts, and driver tracking. Alongside the outbound API, the platform also receives inbound webhooks and callbacks from a range of integration partners (tracking and visibility providers, load boards and marketplaces, carrier onboarding networks, freight claims, and similar), plus a small set of customer-integration create endpoints. Requests to the public API also pass through an edge layer that counts them against configured per-organization and per-API-key limits. This article is for internal staff supporting integrations; it should not be shared with customers.

How it works

There are eight related pieces to understand:

  • The versioned public API. The current external contract is version 2. It is organized by business area, and each area exposes its resources under a versioned path (for example, Shipping, Accounting, and Driver Tracking each have their own v2 resources) so integrators always know which version they are calling. A few shipment-tracking routes use a newer "v3" path. This is the stable, documented surface partners are expected to use. The API documentation still lists both a "V1" and a "V2" document. Operations that are pending end of life are consolidated in a single "Deprecated" group of about two dozen v2 operations (booking a domestic shipment, shipment details, the activity log, reference-number updates, alerts, tracking updates, and the by-id, by-shipment, and confirm-sync operations for invoices, bills, and their payments). Those deprecated operations are still served; they are not removed.

  • Retirement of v1 operations. The original v1 operations are being removed in stages, and several now fail. What remains of v1 is a small shipping area: three rate-quote operations (LTL, truckload, and domestic freight), which still work and take the API key in the request body rather than in a header, and three lookup operations (the accessorial list, shipment documents, and zip-code lookup), which take the key in the address and answer "not found" with a message that the API is fully deprecated and callers should move to v2 once the retirement switch for that stage is on. Everything else from v1 has been deleted outright, including booking a domestic shipment, shipment status reads, the set-status operations for canceled, delivered, picked up, and booked, the custom document uploader, the customer authentication check, and the marketplace "set booked" callback. A deleted v1 route now answers as a plain "no route found" rather than with the deprecation message. When a customer reports a v1 integration that has stopped working, check which of these categories it falls into before anything else.

  • How callers authenticate. Every v2 call is authenticated with an API key that the caller sends in a request header (the x-api-key header). If the key is missing or not valid, or if validation fails for any reason, the request is rejected as unauthorized before any work is done. The only v2 area without that check is a demonstration area that returns example webhook payloads. The public API also offers a token endpoint, protected by the same API key, that issues a signed access token for a user. That token is not a bearer credential for the v2 endpoints. It is a five-minute sign-in handoff that the web application accepts to log a person in, and it is rejected unless the host in the token matches the request. The token endpoint has its own conditions: the API key's user must be a site administrator at an invoice-level accounting organization, and the person being signed in must be an active staff member of an active organization under the same accounting organization. Every issuance, successful or not, is written to the authentication log.

  • Permissions inside the API. Beyond the key, individual operations check the permissions of the key's user. The accounting variance operations require the payables pair (invoicing and revisions) for bills and the receivables pair (invoicing and revisions) for invoices. Shipment and tracking operations only reach shipments the caller's organization can access, and tracking operations also verify that the shipment stop belongs to the caller's organization.

  • Driver tracking (v2). The public API exposes a driver-tracking area so partners and customers can start, update, refresh, cancel, read, and message a shipment's tracking session over the API. It follows the same v2 conventions as the other areas (API-key authentication, open cross-origin configuration, documentation opt-in, and activity logging). The rules are:

    • Every call requires the shipment to be accessible to the caller; otherwise the answer is "not found."
    • A shipment can have only one tracking session. Starting a second one fails with "Tracking already exists." The integration source named in the request must be an external-tracking source owned by, or linked to, the caller's organization. A new session starts active, with a "Started" status unless the caller supplies one, a one-hour update frequency unless supplied, and an external reference id cut to 36 characters; optional flags can require a delivery signature or a proof-of-delivery image. A private operations note records that tracking was started through the API.
    • Update, refresh, and message work only on an active session; a completed or canceled session is treated as "no existing tracking session." Cancel and read work on a session in any state. For update, refresh, cancel, and message, the integration source in the request must match the session's and belong to the caller's organization.
    • An update changes only the fields supplied. If it carries a recent-status text, that text is also written to the shipment's location history as an in-transit point from the external-tracking source (de-duplicated within four minutes). Moving a session to canceled can start a workflow-automation trigger, but only where that trigger is enabled.
    • Refresh marks the session to update ahead of its schedule. Cancel deletes the session. Message only writes a private activity note ("Message sent to driver"); the platform does not send anything to the driver itself.
    • The allowed update frequencies are 10, 20, 30, 45, 60, 120, 240, 360, 480, and 720 minutes.
  • Variance resolution (v2 accounting). Two operations sit beside the existing "send to variance" operations. The bill operation moves a bill's carrier-side charge lines that are currently in variance back to ready, without changing any amount, and records a private payables note. It fails with "Bill is not in variance" if none are in variance. The invoice operation does the same for the customer-side charge lines of the caller's accounting organization on a shipment and records a private receivables note; it fails with "Shipment is not in variance" when nothing is in variance. Calling either one a second time after it has succeeded therefore returns an error. The entry operations refuse to send a bill to variance if accounting has already started on any selected charge line, and refuse to send an invoice to variance if any selected line is already invoiced, has no accounting, or is a pass-through. Sell-side and buy-side charge updates through the API are no longer blocked while a shipment is in variance.

  • Edge rate limiting. In front of the public API sits an edge layer (a Cloudflare worker) that counts each request per API key and per accounting organization against configured limits, with separate per-minute, per-day, and per-month quotas, any of which can be left unlimited. The quotas are edited by IT support staff on a rate-limits screen, stored in the main database, and pushed out to the edge on a schedule by background jobs. A separate administration screen shows request and over-limit history. Only an allow-list of public API paths is counted: accounting, authentication, brokers, carriers, general ledger, load boards, locations, organizations, sales reps, shipment commissions, shipment stops, staff, customers (v2), the Highway carrier confirmation, and shipping v2 and v3. Driver tracking, the v1 shipping area, and the inbound webhooks are not on the list and are never counted. Because the counting happens at the edge and not inside the application, there is no in-app rate-limit check; a call that passes API-key authentication is a separate matter from whether it was within its edge quota. In its current form the edge layer only observes: it records usage and flags when a limit is exceeded (via response headers) but does not block or reject over-limit traffic. See the internal limitations article for the caveats that follow from this.

  • Inbound partner webhooks. Partners send events into the platform through webhook and callback endpoints, grouped roughly as follows:

    • Tracking and visibility: FourKites, MacroPoint, TruckerTools, OpenTrack, FarEye, and QUED (stop updates).
    • Load boards and marketplaces: DAT Convoy, Truckstop, DexFreight, Motive (formerly Keep Truckin) book-it-now, TruckerTools book-it-now, CargoChief, and Parade (carrier quotes, capacity, and reservations).
    • Carrier onboarding and rate confirmation: Highway (carrier alerts, onboarding packet, and carrier confirmation) and Highway TFX.
    • Freight claims and customer-specific feeds: Freight Claims, HubTrans, and Shipco.
    • Customer-integration endpoints that create a shipment, a customer, or a customer staff member, and an older driver-tracking status endpoint that is hidden from the documentation.
    • An internal engineering notification from the source-control system about merge conflicts.
    • The payments webhook is not in this area; it lives with the internal API and has its own validation.

    Unlike the outbound API, these do not all use one authentication method:

    • A token supplied in an authorization header, validated against the API key store (CargoChief, FarEye, and Parade). A missing header returns 400; a wrong scheme or invalid key returns 401.
    • A key in a partner-specific header (FourKites; missing returns 401).
    • A customer identifier plus a key, both in headers (Freight Claims; a mismatch returns 401 and misconfigured staff returns 403).
    • A key compared with a configured value (QUED).
    • A credential embedded in the callback address: a token (two Highway callbacks), a key (HubTrans and the customer-integration create endpoints), or a secret identifier (the engineering notification, which returns 401 on a mismatch).
    • No credential check visible at the endpoint itself for DAT Convoy, DexFreight, Highway TFX, Motive book-it-now, MacroPoint, OpenTrack, Shipco, TruckerTools (both endpoints), and Truckstop. The older driver-tracking status endpoint only rejects a blank key and never validates it. Any protection for those would have to come from checks deeper in the processing, partner network controls, or edge controls, which has not been confirmed.

    Webhook activity is logged. Because different partners authenticate differently, the specific failure responses can also differ between webhook endpoints (a missing credential versus an invalid one may return different error codes). Partners sometimes key their retry behavior on these responses, so the distinctions matter when supporting an integration.

Business rules & limits

  • The public API is versioned and the current version is v2. Resources are exposed under a versioned path so integrators are always calling a known version of the contract.
  • Released API shapes are frozen. Once a version is published, its request and response shapes are treated as a stable contract. Changes are additive only: new fields or new endpoints can be added, but existing shapes are not changed in place. A change that would break existing callers requires a new version rather than an edit to the released one. New fields are often gated behind a feature flag so they only populate when a capability is turned on, which keeps the change additive. Because the API's data shapes are shared internally, staff must be careful that an "internal" refactor of a shared model does not silently alter the external contract. The one sanctioned way a released shape goes away is the staged v1 retirement described above.
  • Deprecated is not deleted. The v2 "Deprecated" group is still live. Only the v1 area is being deleted.
  • API key authenticates v2; the token endpoint issues a short-lived sign-in handoff. The API key gates the v2 operations and the token-issuance request. The issued token expires after five minutes and is not accepted by the v2 operations.
  • Optional-versus-zero is preserved on selected request fields. For a handful of shipment and commodity fields (stackable, service level, handling quantity, weight, hazardous material, and pieces), the platform can tell a field the caller omitted from one the caller deliberately set to zero or false, so only deliberate changes are logged as changes.
  • Rate limiting lives at the edge, not in the app, and only for allow-listed paths. Per-organization and per-API-key quotas (per-minute, per-day, per-month) are configured internally, stored in the main database, and synced to the Cloudflare edge by background jobs. There is no rate-limit filter in the application itself, so passing API-key authentication says nothing about whether a caller was within quota. The edge counting is currently observe-only (it flags but does not block over-limit traffic), counts only the allow-listed paths, and fails open. Changes to a limit can take about a minute to take effect at an edge location that has cached the old owner. The sync of quotas to the edge runs in the production environment only, so off-production environments never receive the quotas.
  • Webhook authentication is per-partner and varied, and some endpoints have none. There is no single webhook authentication method. Do not assume one scheme across all partners; each webhook is secured in the manner its partner requires (or not at all, at the endpoint), and the error responses can differ between them. Do not copy an unauthenticated webhook as a pattern for a new one.
  • Documentation visibility is opt-in. Only endpoints explicitly opted into the published documentation appear there, and some documentation inclusion differs between environments. An endpoint can exist and function without appearing in the published docs, so the docs are not a complete inventory of what is available.
  • Staff-only caveat: the v2 endpoints allow permissive cross-origin access. The public v2 endpoints are configured to accept cross-origin browser requests from any origin. Combined with header-based API keys, this broad cross-origin configuration is a known review item and should be treated as sensitive internal information, not shared externally.

Frequently asked questions

What is the public API in the Tai TMS, and how is it different from the internal API?

In the Tai TMS the public API is an external, versioned contract (currently version 2) that customers and integration partners build against for areas such as shipments, invoices, bills, payments, load boards, and driver tracking. It is deliberately separate from the internal endpoints the product's own screens use: the public API is authenticated with an API key and is meant for third parties, whereas the internal endpoints serve the application's own user interface under the signed-in user's session.

How do callers authenticate to the Tai TMS public API?

Callers authenticate to the Tai TMS v2 public API with an API key sent in the x-api-key request header. If the key is missing or invalid, the request is rejected as unauthorized. The public API also provides a token endpoint, itself protected by the API key and restricted to site-administrator keys, that issues a signed five-minute token for a user. That token is a sign-in handoff for the web application, not a credential for the v2 endpoints. The few remaining v1 rate-quote operations take the key in the request body instead of a header.

A customer says their old v1 integration stopped working. What happened?

The Tai TMS is retiring the original v1 operations in stages. Booking a domestic shipment, reading or setting shipment status, the custom document uploader, the customer authentication check, and the marketplace booked callback have been deleted, so those routes now return a plain "not found." The accessorial list, shipment documents, and zip-code lookup return a message that the API is fully deprecated once their retirement switch is on. Only the three v1 rate-quote operations still work. The customer should move to the equivalent v2 operations; the v2 "Deprecated" group is still served but is itself pending end of life.

How is the public API rate-limited?

Requests pass through an edge layer (a Cloudflare worker) in front of the API that counts them per API key and per accounting organization against configured per-minute, per-day, and per-month quotas. Staff configure those quotas on an internal rate-limits screen; they are stored in the main database and pushed to the edge by scheduled background jobs. Things worth knowing internally: the edge layer currently only observes usage (it flags an over-limit request with response headers but does not block it); only an allow-list of path prefixes is counted, so driver tracking and the inbound webhooks are never counted; and the quota sync runs in production only, so non-production environments never receive quotas. There is no rate-limit check inside the application itself.

How are inbound partner webhooks secured in the Tai TMS?

In the Tai TMS, inbound partner webhooks are secured per partner rather than with a single shared method. Depending on the partner, a webhook may require a token in an authorization header, a key in a partner-specific header, a customer identifier combined with a key, a key matched against a configured value, or a credential embedded in the callback address. Several partner endpoints (DAT Convoy, DexFreight, Highway TFX, Motive book-it-now, MacroPoint, OpenTrack, Shipco, TruckerTools, and Truckstop) show no credential check at the endpoint itself, which is a known review item. The error responses can differ between endpoints.

If we need to change a field in the public API, can we just edit it?

No. In the Tai TMS the released public API shapes are treated as a frozen contract, and changes must be additive: you can add new fields or endpoints, but you must not change existing request or response shapes in place. A change that would break existing callers requires introducing a new version. New fields are commonly gated behind a feature flag so they populate only when a capability is enabled. Because the API's data shapes are shared internally, take care that an internal model refactor does not unintentionally alter the external contract.

What can an integration do with driver tracking over the public API?

In the Tai TMS, an integration with an external-tracking source can start a tracking session for a shipment (one session per shipment), update it, ask for an early refresh, cancel it, read it, and log a message to the driver. Updates with a status text also add an in-transit point to the shipment's location history. The platform records these actions in the shipment's activity log but does not itself send the message to the driver. Each call requires the integration source to belong to the caller's organization and the shipment to be accessible to the caller.

What does the public API variance "resolve" operation do?

In the Tai TMS, resolving a bill or invoice variance through the public API moves the charge lines that are currently in variance back to ready, without changing any amounts. The caller needs the payables pair of permissions (invoicing and revisions) for bills, or the receivables pair for invoices. If nothing is in variance, the call returns an error ("Bill is not in variance" or "Shipment is not in variance"), so repeating a successful call fails.

Why might a public API endpoint work but not appear in the documentation?

In the Tai TMS, inclusion in the published API documentation is opt-in, and it can also differ between environments. An endpoint can be fully functional yet not appear in the docs because it was not opted in for that environment. As a result, the published documentation is not a guaranteed complete inventory of every available endpoint.

Is there anything about the public API's cross-origin configuration staff should know?

Yes, as an internal note: the Tai TMS public v2 endpoints are configured to accept cross-origin browser requests from any origin. Combined with the header-based API key model, this permissive cross-origin setting is a known internal review item. It is staff-only context and should not be shared with customers.