Carrier API Token TTLs: 14 Vendors Measured

Access and refresh token lifetimes for 14 carrier and multi-carrier APIs, sourced from vendor docs, with token-cache design guidance.

Carrier API Token TTLs: 14 Vendors Measured

We pulled the OAuth and API-key expiry figures for 14 carrier and multi-carrier API surfaces, and the spread is bigger than most integration code accounts for. Access tokens range from 28 minutes to 12 hours. Some vendors hand out a refresh token, most don't. And at least one major carrier just cut its token lifespan by 75% with roughly four months' notice. If your token cache treats "carrier API token expiry" as a fixed constant somewhere in a config file, this is the post that tells you why that's a liability.

Why token TTL is an architecture problem, not a config value

Multi-tenant middleware holding credentials for dozens of carriers, across hundreds of tenants, cannot run on one refresh interval. A value hardcoded against one carrier's token lifetime works fine right up until that carrier changes it, and carriers do change it.

Case in point: UPS. Pitney Bowes' support notice confirms that starting April 1, 2026, the lifespan of OAuth tokens will change from 4 hours to 1 hour, and that this update impacts how integrations manage token refresh logic. Any integration that assumed a 4-hour window and refreshed on that schedule started throwing invalid-credential errors the moment the switch flipped. No API version bump, no breaking-change header, just a shorter clock.

This is the entire argument for reading expires_in from every token response rather than trusting a number you wrote down once. We measured what that number actually is, per vendor, as of now.

The numbers: access and refresh token TTLs across 14 API surfaces

The table below lists the access token TTL, whether a refresh token is issued, and the primary source for each carrier API and multi-carrier platform surface we checked. Where a figure isn't published anywhere we could find, it's marked "Not published" rather than guessed.

Vendor / API surfaceAccess token TTLRefresh token issuedSource
FedEx Ship/Track/Rate APIs60 minutesNoFedEx Developer Portal, authorization docs
FedEx Supply Chain API1 hourYes, 31 days (2,682,000s), max 4,096 refresh calls per appFedEx Supply Chain OAuth docs
UPS (Client Credentials, all APIs)1 hour as of 1 April 2026 (was 4 hours)Not publishedPitney Bowes support notice
DHL Post & Parcel Germany30 minutesNo (ROPC flow, re-authenticate)DHL Developer Portal, Authentication API
DHL eCommerce Americas60 minutesNoDHL Developer Portal, Authentication API
DHL eCommerce UKNot publishedNot publishedDHL Developer Portal
DHL FreightNot publishedNot publishedDHL Developer Portal
DHL Parcel NL (My DHL Parcel)Not published (variable, per response field)Yes, per response fieldMy DHL Parcel API guide
USPS APIs v3, OAuth Bearer token8 hoursNo (client credentials grant)USPS Onboarding Guide v6.0
USPS Payment Authorization token8 hoursNoUSPS Onboarding Guide v6.0
Shippo core APINo expiry (static key, revocation only)N/AShippo API documentation
Shippo Shipping Elements (embedded JWT)12 hoursRefresh flow available client-sideShippo Shipping Elements auth guide
ShipEngine / ShipStation APINo expiry (static API key, revocation only)N/AShipEngine Auth docs
Sendcloud (legacy Basic Auth / v3 OAuth2 beta)No expiry (legacy) / 3,600s (v3 beta)No (legacy) / Yes, via id_token scope (v3 beta)Sendcloud API docs / OAuth2 token endpoint

A few figures are worth pulling out explicitly. FedEx's flagship Ship/Track/Rate APIs state that this OAuth access token needs to be regenerated after every 60 minutes and provided with each API transaction, and it issues no refresh token at all, every renewal is a fresh client-credentials call. Its Supply Chain API is more generous: the access token typically expires in 1 hour, and the refresh token expires in 31 days (2,682,000 seconds), with a maximum number of times a refresh token can be requested set to 4,096 per application.

DHL's Post & Parcel Germany documentation is unambiguous that the access token does expire after 30 minutes, and after expiration you have to request a new token. Its eCommerce Americas API technically allows 60 minutes but hedges: an access token is valid for a certain amount of time before it expires, and this limit is currently set to 60 minutes, while DHL itself recommends that you refresh the access token periodically (~15 mins to 30 mins) so that none of the resource requests receive an error due to an expired access token. That's a vendor telling you not to trust its own published ceiling.

USPS sits at the long end of the direct-carrier range. Its onboarding guide states an OAuth token is required which will enable access to USPS APIs and is valid for 8 hours. But third-party integration guidance warns this number is a ceiling, not a promise: RevAddress's troubleshooting guide notes to use a 30-minute buffer, not 5 minutes, because USPS tokens can be invalidated before their stated expiry.

On the multi-carrier side, Shippo's core REST API runs on a static account-scoped Bearer token passed as Authorization: ShippoToken, with no OAuth 2.0 and no per-user token delegation, so there's no TTL to track at all, only revocation. Its embedded Shipping Elements product is different: your generated JWT expires after 12 hours. ShipEngine (now rebranding as ShipStation API) is the same static-key model: if you don't include a key when making an API request, or if you use an incorrect or expired key, ShipStation API will respond with a 401 Unauthorized error, with no published rotation schedule beyond manual revocation. Sendcloud's newer v3 OAuth2 flow, still in beta, follows the standard pattern: the value "3600" denotes that the access token will expire in one hour from the time the response was generated, and it's currently available as a beta feature for a limited number of clients.

Method: what we checked, and what we didn't

Figures were pulled directly from each vendor's current developer documentation, published OAuth/OpenAPI reference pages, or dated support notices, checked as of 12 August 2026. Every figure in the table traces to a primary source; nothing here is interpolated from a related product or estimated from typical OAuth defaults.

The scope has real gaps, and it's worth being upfront about them:

  • Sandbox-versus-production TTL drift was not verified per vendor. Several developer portals show identical numbers in both environments, but we did not independently confirm this for every API in the table.
  • Label-download tokens and webhook signing secrets are a separate credential class entirely and are out of scope for this comparison.
  • Regional carriers including GLS, DPD, PostNL, and bpost were not tested for this round and don't appear in the table. We'd rather leave them out than guess.
  • Rate limits, quota resets, and IP allow-listing rules are separate mechanisms from token expiry and aren't covered here.

The pattern in the data

Three clusters emerge. The large parcel carriers converge on roughly an hour: FedEx's Ship/Track/Rate API and Supply Chain API both sit at 60 minutes, and UPS now matches that as of April 2026. DHL splits itself across a shorter band, 30 minutes on its ROPC-based Post & Parcel Germany service, and a nominal 60 minutes (with an informal 15-to-30-minute recommendation) on eCommerce Americas. USPS is the outlier among direct carriers at 8 hours, though its own third-party tooling warns that number isn't a guarantee.

Static, non-expiring API keys are still common, but only among the multi-carrier abstraction layer, not the carriers themselves: Shippo's core API and ShipEngine both run on revocation-only Bearer tokens with no TTL at all.

That split isn't accidental. Carriers issuing OAuth directly to shippers favour short-lived bearer tokens because it limits the blast radius of a leaked credential. Multi-carrier platforms favour static keys or longer-lived tokens on their own surface because they, not the shipper, absorb the churn of the underlying carrier OAuth flows. That absorption is precisely what platforms like ShipEngine, Shippo, Sendcloud, EasyPost, nShift, and Cargoson sell as part of their value: one stable credential model on top of a dozen carrier-side token lifecycles that keep moving underneath it.

Design implications for a multi-tenant token cache

If you're building or operating the middleware layer yourself rather than buying the abstraction, the UPS change is the lesson to design against, not the exception. A few concrete rules follow directly from the data above.

Never hardcode a refresh interval. Always read expires_in from the token response itself and cache against it. Key the cache by tenant and carrier and credential set, not just by carrier, since two tenants on the same carrier may hold different client secrets with different rotation schedules.

Renew ahead of expiry, not at expiry. A jittered renew-at-roughly-90%-of-TTL strategy avoids two failure modes at once: requests failing on a token that expired mid-flight, and a refresh stampede when many tenants share a rate-limited carrier client and all renew in the same second.

A cache entry for this needs at minimum:

{
  "tenant_id": "t_8841",
  "carrier": "fedex_supply_chain",
  "access_token": "eyJhbGc...",
  "expires_at": "2026-08-12T14:03:00Z",
  "refresh_token": "yFGvLOKW",   // null for FedEx Ship/Track/Rate, ShipEngine, Shippo core
  "refresh_count": 12,           // relevant for FedEx Supply Chain's 4,096 cap
  "renew_after": "2026-08-12T13:58:12Z"
}

Note the nullable refresh_token field. Most of the carrier-direct APIs in the table above don't issue one at all, FedEx Supply Chain and DHL Parcel NL are among the few exceptions, so a cache schema that assumes every carrier gives you a refresh token will sit empty for most rows.

Finally, treat expires_in as an upper bound, not a guarantee. USPS's early-revocation behaviour is the clearest published example of a carrier reserving the right to invalidate a token before its stated expiry, but it's a reasonable default assumption for any carrier token, not just USPS's.

Where this leaves you

Default to short-lived, per-carrier token caches driven entirely by server-provided TTLs, and treat any hardcoded refresh window still living in your codebase as technical debt to retire this quarter. If you're evaluating a multi-carrier platform instead of maintaining direct carrier connections, the question worth asking isn't just which carriers it supports, it's how it isolates your integration from the next carrier that quietly halves its token lifespan.