Skip to main content

USPS v3 REST API client — OAuth 2.0, address validation, tracking, labels, rates. Drop-in replacement for usps-api (retired Jan 2026).

Project description

usps-v3

PyPI License: MIT RevAddress

USPS v3 REST API client — OAuth 2.0, address validation, tracking, labels, rates. Drop-in replacement for the usps-api PyPI package (retired January 2026).

Direct USPS integration. OAuth 2.0. No middleman. No per-label fees.

Migrating from usps-api? That package (13,700+ downloads/month) uses the retired USPS Web Tools XML API (shut down January 25, 2026). This SDK uses the new v3 REST API with OAuth 2.0. See Migration from usps-api below.

Don't want to manage USPS credentials? RevAddress provides a managed USPS v3 API with flat monthly pricing, rate limit handling, and BYOK support. Get a free sandbox key — no credit card required.

Migrating from EasyPost or USPS Web Tools?

RevAddress provides a managed USPS v3 API with flat monthly pricing — no per-label fees. If you're migrating from EasyPost (shutting down March 17, 2026) or the legacy USPS Web Tools XML API:

Save 81% vs EasyPost at 5,000 labels/mo ($79/mo flat vs $420 in per-label fees). Get started →

Install

pip install usps-v3

Quick Start

from usps_v3 import Client

# Credentials from USPS Business Customer Gateway
client = Client(client_id="your-id", client_secret="your-secret")
# Or set USPS_CLIENT_ID and USPS_CLIENT_SECRET environment variables:
# client = Client()

# Validate an address (FREE)
result = client.addresses.validate(
    street_address="1600 Pennsylvania Ave NW",
    city="Washington",
    state="DC",
    zip_code="20500",
)
print(result["address"]["ZIPPlus4"])  # "0005"

# Track a package (FREE)
info = client.tracking.track("9400111899223033005282")
print(info["statusCategory"])  # "Delivered"

# Get delivery time estimates (FREE)
standards = client.standards.estimates("10001", "90210")

# Find drop-off locations (FREE)
locations = client.locations.dropoff("20500", mail_class="PRIORITY_MAIL")

# Get rate quotes
rates = client.prices.domestic("10001", "90210", weight=2.5)
print(rates["rates"]["rateOptions"][0]["totalPrice"])

# International rates
intl = client.prices.international("10001", "CA", weight=3.0)

# Create shipping labels (requires USPS enrollment + COP claims)
label = client.labels.create(
    from_address={"streetAddress": "123 Sender St", "city": "New York", "state": "NY", "ZIPCode": "10001"},
    to_address={"streetAddress": "456 Recipient Ave", "city": "LA", "state": "CA", "ZIPCode": "90001"},
    mail_class="PRIORITY_MAIL",
    weight=2.0,
)
print(label["trackingNumber"])

# Void a label
client.labels.void("9400111899223033005282")

Features

Feature Endpoint Auth Required
Address Validation addresses.validate() OAuth only
City/State Lookup addresses.city_state() OAuth only
Package Tracking tracking.track() OAuth only
Service Standards standards.estimates() OAuth only
Drop-off Locations locations.dropoff() OAuth only
Domestic Prices prices.domestic() OAuth only
International Prices prices.international() OAuth only
Label Creation labels.create() OAuth + Payment Auth
Label Void labels.void() OAuth only

Authentication

The SDK handles OAuth 2.0 token lifecycle automatically:

  • Token caching: Tokens are cached in memory and on disk (~/.usps-v3/tokens.json)
  • Auto-refresh: Tokens refresh automatically 30 minutes before expiry
  • Thread-safe: Safe for concurrent use across threads

Getting Credentials

  1. Register at USPS Business Customer Gateway
  2. Create an application in the API developer portal
  3. Note your client_id and client_secret

For label creation, you also need:

  • CRID (Customer Registration ID)
  • MIDs (Mailer IDs — master + label owner)
  • EPA (Enterprise Payment Account)
  • COP claims linking at cop.usps.com

See our USPS CRID/MID enrollment guide for step-by-step instructions.

client = Client(
    client_id="...",
    client_secret="...",
    crid="56982563",
    master_mid="904128936",
    label_mid="904128937",
    epa_account="1000405525",
)

Error Handling

from usps_v3 import Client, AuthError, ValidationError, RateLimitError, APIError

try:
    result = client.addresses.validate(street_address="123 Main St")
except ValidationError as e:
    print(f"Bad input: {e} (field: {e.field})")
except RateLimitError as e:
    print(f"Rate limited — retry after {e.retry_after}s")
except AuthError as e:
    print(f"Auth failed: {e}")
except APIError as e:
    print(f"USPS error ({e.status_code}): {e}")

USPS Rate Limits

The v3 API defaults to 60 requests/hour (down from unlimited in Web Tools). The SDK does not enforce this limit — USPS returns 429 when exceeded.

To request a higher limit, contact USPS at emailus.usps.com. See our USPS rate limits guide for details.

Migration from usps-api

The usps-api PyPI package (13,700+ downloads/month) uses the retired USPS Web Tools XML API (shut down January 25, 2026). If you're migrating from usps-api or any Web Tools XML integration:

Web Tools (XML) v3 SDK (Python)
<AddressValidateRequest> client.addresses.validate(...)
<CityStateLookupRequest> client.addresses.city_state(...)
<TrackFieldRequest> client.tracking.track(...)
<RateV4Request> client.prices.domestic(...)
User ID auth OAuth 2.0 (automatic)
XML response parsing Python dicts (automatic)
Unlimited requests 60/hr default (request increase)

See our complete migration guide and Web Tools endpoint mapping for detailed migration instructions.

RevAddress Managed API

If you'd rather not manage USPS OAuth credentials, rate limits, and enrollment yourself, RevAddress offers a managed REST API:

  • Drop-in USPS v3 API — same endpoints, managed OAuth
  • Flat monthly pricing — no per-label fees (from $29/mo)
  • Rate limit handling — 120-600 req/min depending on plan
  • BYOK support — bring your own USPS credentials
  • 293 tests, 41 routes — production-grade infrastructure

Get a free sandbox key — address validation, tracking, and rate shopping included. No credit card required.

Development

git clone https://github.com/revereveal/usps-v3.git
cd usps-v3
pip install -e ".[dev]"
pytest -v

Links

License

MIT — see LICENSE.

Built by RevAddress — managed USPS API infrastructure for developers and businesses.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

usps_v3-1.0.4.tar.gz (20.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

usps_v3-1.0.4-py3-none-any.whl (21.0 kB view details)

Uploaded Python 3

File details

Details for the file usps_v3-1.0.4.tar.gz.

File metadata

  • Download URL: usps_v3-1.0.4.tar.gz
  • Upload date:
  • Size: 20.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for usps_v3-1.0.4.tar.gz
Algorithm Hash digest
SHA256 6a2146768268259271879e1981cb6c998d06937c8bf14426e7029ae1fcdac928
MD5 5bd3a038ee3e7fdb0c46b27f26462fec
BLAKE2b-256 9e1d659e546f7a2e39a47c6b1161dbfc78bb09a247ae67c71fd3d6526397257f

See more details on using hashes here.

File details

Details for the file usps_v3-1.0.4-py3-none-any.whl.

File metadata

  • Download URL: usps_v3-1.0.4-py3-none-any.whl
  • Upload date:
  • Size: 21.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for usps_v3-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 8c369767d660599f4e709bc63dd6627b117338b3d5c73b4a2247a39affc53835
MD5 79806d79f8c50d5ef3cdd0438dac1231
BLAKE2b-256 3a19ec5809c21e761f5f2d7c6cdd8102cce2da8a8253df12fc74e45d4deb1df0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page