Skip to content

Quickstart — first response in 60 seconds

  1. 1

    Get Free API Key

    No credit card required. Takes 10 seconds.

    Get Free API Key
  2. 2

    Validate an address

    curl "https://api.revaddress.com/api/address/validate?streetAddress=1600+Pennsylvania+Ave&city=Washington&state=DC&ZIPCode=20500"
  3. 3

    Explore the full API

    Start with the free proof surface — validation, ZIP+4, and rate shopping — then expand into label workflows, BYOK, and rollout-gated tracking or pickup access.

    Full API Reference →

Land-and-expand access model

RevAddress is the USPS v3 developer toolkit. Start with the free tier — address validation, extract, ZIP+4, city/state, and rates — then add tracking, intelligence, BYOK, and batch validation when you need them.

Free tier
  • Address validation + extract
  • ZIP+4 + city/state lookup
  • Domestic + international rate shopping
  • Service standards, shipping options, and locations

Try every validation and rate endpoint with live USPS responses. No API key required.

API key required
  • Package tracking
  • Batch validation + checkout widget
  • Dashboard + BYOK
  • Pickup scheduling

Paid endpoints unlock after signup. Flat monthly pricing.

Higher volume
  • Increased throughput
  • Enterprise onboarding
  • Custom integrations

Contact us when volume or licensing needs exceed standard tiers.

Authentication

Use the X-API-Key header for protected workflows such as tracking, labels, batch validation, request-access pickup, dashboard usage, and BYOK. The free proof tier also covers address validation, address extract, ZIP+4 city/state lookup, domestic and international rates, service standards, shipping options, and locations on the IP-rate-limited public tier. Use a free API key when you want one identity across the docs and dashboard, then expand into protected production workflows when you're ready.

curl -H "X-API-Key: rv_live_your_key_here" \
  https://api.revaddress.com/api/address/validate?streetAddress=1600+Pennsylvania+Ave&city=Washington&state=DC&ZIPCode=20500

Address Validation

Validate and standardize US addresses using USPS CASS-certified data. Returns DPV confirmation, ZIP+4, and delivery indicators. Free Tier

GET /api/address/validate
  ?streetAddress=1600+Pennsylvania+Ave
  &secondaryAddress=Suite+100
  &city=Washington
  &state=DC
  &ZIPCode=20500

// Response
{
  "address": {
    "streetAddress": "1600 PENNSYLVANIA AVE NW",
    "secondaryAddress": "STE 100",
    "city": "WASHINGTON",
    "state": "DC",
    "ZIPCode": "20500",
    "ZIPPlus4": "0005"
  },
  "additionalInfo": {
    "DPVConfirmation": "Y",
    "vacant": "N",
    "deliveryPoint": "00",
    "business": "Y"
  },
  "matches": [{ "code": "31", "text": "Single Response - exact match" }],
  "resolution": {
    "classification": "deliverable_exact",
    "nextAction": "done",
    "userMessage": "USPS confirmed this address."
  }
}

City & State Lookup

Look up city and state from a ZIP code. Returns all valid city names for the ZIP. Free Tier

GET /api/address/city-state?zip=10001

// Response
{
  "zip5": "10001",
  "city": "NEW YORK",
  "state": "NY"
}

Batch Address Validation

Validate up to 50 addresses in a single request using Promise.allSettled — every address gets a result even if some fail. Responses include per-address timing. Results are KV-cached for 24 hours. Growth+

POST /api/batch/validate
Content-Type: application/json

{
  "addresses": [
    { "streetAddress": "1600 Pennsylvania Ave", "city": "Washington", "state": "DC", "ZIPCode": "20500" },
    { "streetAddress": "350 Fifth Avenue", "city": "New York", "state": "NY", "ZIPCode": "10118" },
    { "streetAddress": "999 Fake St", "city": "Nowhere", "state": "XX", "ZIPCode": "00000" }
  ]
}

// Response — every address gets a result
{
  "results": [
    { "status": "fulfilled", "value": { "streetAddress": "1600 PENNSYLVANIA AVE NW", "ZIPPlus4": "20500-0005", "DPVConfirmation": "Y" } },
    { "status": "fulfilled", "value": { "streetAddress": "350 5TH AVE", "ZIPPlus4": "10118-0110", "DPVConfirmation": "Y" } },
    { "status": "rejected", "reason": { "error": "ADDRESS_NOT_FOUND", "message": "Address not found" } }
  ],
  "summary": { "total": 3, "fulfilled": 2, "rejected": 1 },
  "timing_ms": 342
}

Package Tracking

Use the managed tracking route for USPS status lookup and normalized tracking data. Tracking is protected behind API keys and plan access while address validation, city/state lookup, and rate shopping remain free to test.

GET /api/tracking/9400111899223456789012

// Response
{
  "tracking_number": "9400111899223456789012",
  "status": "Pre-Shipment",
  "status_detail": "Shipping Label Created, USPS Awaiting Item",
  "location": "NEW YORK, NY 10003",
  "events": [
    {
      "timestamp": "2026-03-17T03:26:34Z",
      "event": "Shipping Label Created, USPS Awaiting Item",
      "city": "NEW YORK",
      "state": "NY"
    }
  ]
}

Domestic Prices

Compare live USPS pricing across all domestic service types. Returns rates for Priority Mail, Ground Advantage, Priority Mail Express, and more. Free Tier

POST /api/rates
Content-Type: application/json

{
  "origin_zip": "10001",
  "destination_zip": "90001",
  "weight_oz": 16,
  "mail_class": "ALL"
}

// Response
{
  "rates": [
    { "service": "PRIORITY_MAIL", "price": 8.70, "delivery_days": 2 },
    { "service": "GROUND_ADVANTAGE", "price": 5.25, "delivery_days": 5 },
    { "service": "PRIORITY_MAIL_EXPRESS", "price": 26.60, "delivery_days": 1 }
  ]
}

International Prices

Get USPS pricing for international shipments. Supports all destination countries and international service types. Requires API key.

POST /api/international-prices
Content-Type: application/json

{
  "destination_country": "GB",
  "weight_oz": 32,
  "mail_class": "ALL"
}

// Response
{
  "rates": [
    { "service": "PRIORITY_MAIL_INTERNATIONAL", "price": 49.50, "delivery_days": 10 },
    { "service": "FIRST_CLASS_MAIL_INTERNATIONAL", "price": 15.25, "delivery_days": 21 }
  ]
}

Label Creation

Create USPS shipping labels through the managed workflow path. Returns workflow, label, download, and refund/void metadata when completed. Requires Growth plan or higher.

POST /api/labels
Content-Type: application/json

{
  "from": {
    "name": "Your Company",
    "street": "123 Sender St",
    "city": "New York",
    "state": "NY",
    "zip": "10001"
  },
  "to": {
    "name": "Recipient",
    "street": "456 Receiver Ave",
    "city": "Los Angeles",
    "state": "CA",
    "zip": "90001"
  },
  "service": "PRIORITY_MAIL",
  "weight_oz": 16
}

// Response
{
  "label_id": "lbl_abc123",
  "tracking_number": "9205590164917312345678",
  "label_url": "https://api.revaddress.com/labels/lbl_abc123.pdf",
  "rate": { "amount": 8.70, "currency": "USD" }
}

Label Management

List your labels, download PDFs, and void unused labels for refund. All operations scoped to your API key.

// List your labels
GET /api/labels

// Download a label PDF
GET /api/labels/lbl_abc123/download

// Void an unused label (refund postage)
POST /api/labels/void/lbl_abc123

// Response
{
  "label_id": "lbl_abc123",
  "status": "voided",
  "refund_status": "pending"
}

Service Standards

Look up USPS delivery time standards between two ZIP codes. Returns estimated delivery days by service type.

GET /api/service-standards
  ?origin_zip=10001
  &destination_zip=90001

// Response
{
  "origin_zip": "10001",
  "destination_zip": "90001",
  "standards": [
    { "service": "PRIORITY_MAIL", "days": 2 },
    { "service": "GROUND_ADVANTAGE", "days": 5 },
    { "service": "PRIORITY_MAIL_EXPRESS", "days": 1 }
  ]
}

Locations

Find USPS post offices, collection boxes, and service locations near a ZIP code or address.

GET /api/locations?zip=10001&radius=5

// Response
{
  "locations": [
    {
      "name": "Midtown Station",
      "address": "223 W 38th St, New York, NY 10018",
      "type": "POST_OFFICE",
      "hours": "Mon-Fri 8am-7pm, Sat 9am-4pm",
      "distance_miles": 0.3
    }
  ]
}

Pickup Scheduling

Pickup endpoints are limited-rollout surfaces. Request access before relying on pickup flows for production operations.

POST /api/pickup
Content-Type: application/json

{
  "address": {
    "street": "123 Sender St",
    "city": "New York",
    "state": "NY",
    "zip": "10001"
  },
  "pickup_date": "2026-03-12",
  "package_count": 3,
  "service": "PRIORITY_MAIL"
}

// Illustrative response shape
{
  "confirmation_number": "WTC123456789",
  "pickup_date": "2026-03-12",
  "status": "pending_confirmation"
}

Shipping Options

Get available USPS shipping options for a given origin/destination pair. Returns eligible service types with features and restrictions.

GET /api/shipping-options
  ?origin_zip=10001
  &destination_zip=90001
  &weight_oz=16

// Response
{
  "options": [
    {
      "service": "PRIORITY_MAIL",
      "features": ["TRACKING", "INSURANCE_INCLUDED"],
      "max_weight_oz": 1120
    },
    {
      "service": "GROUND_ADVANTAGE",
      "features": ["TRACKING"],
      "max_weight_oz": 1120
    }
  ]
}

BYOK (Bring Your Own Keys)

Use your own USPS Developer Portal credentials with our infrastructure. Your credentials are AES-GCM encrypted at rest. Available on Pro and Enterprise plans.

// Store your USPS credentials (encrypted at rest)
POST /api/byok/credentials
Content-Type: application/json

{
  "client_id": "your_usps_client_id",
  "client_secret": "your_usps_client_secret",
  "crid": "your_crid",
  "mid": "your_mid"
}

// Check credential status
GET /api/byok/status

// Verify credentials work
POST /api/byok/verify

// Response
{
  "status": "verified",
  "last_verified_at": "2026-03-09T20:00:00Z",
  "token_healthy": true
}

// Remove your credentials
DELETE /api/byok/credentials

Webhook Notifications

Webhook registration is available in limited rollout for tracking status updates. Register a URL when event delivery is enabled for your account. Payloads are HMAC-SHA256 signed so you can verify authenticity. Requires Starter plan or above. Maximum 5 endpoints per merchant.

// Register a webhook endpoint
POST /api/my/webhooks
Content-Type: application/json

{
  "url": "https://your-app.com/webhooks/tracking",
  "events": ["tracking.status_changed", "tracking.alert"]
}

// Response (secret shown ONLY on creation — save it!)
{
  "id": "wh_abc123",
  "url": "https://your-app.com/webhooks/tracking",
  "events": ["tracking.status_changed", "tracking.alert"],
  "secret": "rv_whsec_a1b2c3d4e5f6..."
}

// Illustrative webhook payload delivered to your URL
POST https://your-app.com/webhooks/tracking
Revaddress-Signature: t=1710000000,v1=5d41402abc...
Content-Type: application/json

{
  "event": "tracking.status_changed",
  "tracking_number": "9400111899223456789012",
  "status": "pre_shipment",
  "data": {
    "statusCategory": "Pre-Shipment",
    "latestEvent": {
      "eventType": "Shipping Label Created, USPS Awaiting Item",
      "eventCity": "NEW YORK",
      "eventState": "NY"
    }
  },
  "timestamp": "2026-03-17T03:26:34.000Z"
}

// Verify the signature — Node.js
const crypto = require('crypto');
const sig = req.headers['revaddress-signature'];
const [tPart, v1Part] = sig.split(',');
const timestamp = tPart.replace('t=', '');
const expected = crypto
  .createHmac('sha256', webhookSecret)
  .update(timestamp + '.' + JSON.stringify(req.body))
  .digest('hex');
const valid = v1Part.replace('v1=', '') === expected;

// Verify the signature — Python
import hmac, hashlib
sig = request.headers['Revaddress-Signature']
parts = dict(p.split('=', 1) for p in sig.split(','))
expected = hmac.new(
    webhook_secret.encode(),
    f"{parts['t']}.{request.data.decode()}".encode(),
    hashlib.sha256
).hexdigest()
valid = hmac.compare_digest(parts['v1'], expected)

// Verify the signature — PHP
$sig = $_SERVER['HTTP_REVADDRESS_SIGNATURE'];
preg_match('/t=(\d+),v1=(.+)/', $sig, $m);
$expected = hash_hmac('sha256',
    $m[1] . '.' . file_get_contents('php://input'),
    $webhookSecret);
$valid = hash_equals($m[2], $expected);

// Manage endpoints
GET /api/my/webhooks           // List all endpoints
DELETE /api/my/webhooks/{id}   // Remove an endpoint

Account Management

View your usage, manage API keys, and check subscription status. All endpoints scoped to your authenticated merchant account.

// View your usage this billing period
GET /api/my/usage

// Response
{
  "merchant_id": "stripe_cus_abc123",
  "period_start": "2026-03-01",
  "total_requests": 1247,
  "by_endpoint": {
    "/api/address/validate": 892,
    "/api/tracking": 231,
    "/api/rates": 124
  }
}

// List your API keys
GET /api/my/keys

// Revoke an API key
DELETE /api/my/keys/{key_hash}

Admin Diagnostics

Admin-only token diagnostics for internal operators. Use Authorization: Bearer {ADMIN_SECRET} to inspect token state, clear cached OAuth/payment tokens, force refreshes, and test payment authorization without buying postage. Internal only

GET /api/tokens/status

// Response
{
  "environment": "production",
  "oauth": { "valid": true, "ttl_seconds": 25120 },
  "payment": {
    "valid": true,
    "ttl_seconds": 23980,
    "lastAttemptAt": "2026-03-15T15:24:11.112Z",
    "lastUpstreamStatus": 200,
    "lastUpstreamMessage": "Payment authorization token obtained",
    "failureClass": null,
    "blockedReason": null
  }
}

POST /api/tokens/clear?env=prod
POST /api/tokens/refresh
POST /api/test-payment-auth

Rate Limits

Rate limits are applied per API key, per minute. Exceeding your limit returns a 429 status. Current limits are returned in response headers. Free tier (no API key): 30 requests per 10 seconds, IP-limited.

// Response headers on every authenticated request
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1709913600

// Tier limits
// Starter:    120 req/min
// Growth:     300 req/min
// Pro:        higher plan limit
// Enterprise: Custom

// When rate limited
HTTP/1.1 429 Too Many Requests
{
  "error": "Rate limit exceeded",
  "retry_after": 42
}

Error Handling

All errors return a consistent JSON structure with machine-readable error codes and human-readable messages.

// 400 Bad Request
{
  "error": "INVALID_ADDRESS",
  "message": "Street address is required",
  "field": "street"
}

// 401 Unauthorized
{
  "error": "INVALID_API_KEY",
  "message": "API key is missing or invalid"
}

// 403 Forbidden
{
  "error": "PLAN_LIMIT",
  "message": "Label creation requires Growth plan or higher"
}

// 429 Too Many Requests
{
  "error": "Rate limit exceeded",
  "retry_after": 42
}

Try It Live

No signup required

RevAddress is the USPS v3 developer toolkit. Start with the free tier — address validation, extract, ZIP+4, city/state, and rates — then add tracking, intelligence, BYOK, and batch validation when you need them.

// Click "Validate Address" to see the live response

Endpoint Summary

Core commercial and operator endpoints across validation, rates, service standards, locations, tracking, label workflows, BYOK, and admin diagnostics.

MethodEndpointAuthPlan
GET/api/address/validateFreeAll
GET/api/address/city-stateFreeAll
POST/api/ratesFreeAll
POST/api/international-pricesFreeAll
GET/api/service-standardsFreeAll
GET/api/shipping-optionsFreeAll
GET/api/locationsFreeAll
GET/api/tracking/:numberAPI KeyStarter+
POST/api/batch/validateAPI KeyGrowth+
POST/api/labelsAPI KeyGrowth+
GET/api/labelsAPI KeyGrowth+
GET/api/labels/:id/downloadAPI KeyGrowth+
POST/api/labels/void/:idAPI KeyGrowth+
POST/api/pickupAPI KeyStarter+
POST/api/my/webhooksAPI KeyStarter+
GET/api/my/webhooksAPI KeyStarter+
POST/api/byok/credentialsAPI KeyPro+
GET/api/byok/statusAPI KeyPro+
GET/api/my/usageAPI KeyAll
GET/api/my/keysAPI KeyAll

SDKs & Libraries

Use our official SDKs for a faster integration.

PythonPyPI · v1.0.2
pip install usps-v3
PyPI ·GitHub · 67 tests · httpx ·Tutorial
Node.jsnpm · v1.0.2
npm install usps-v3
npm ·GitHub · 58 tests · zero deps ·Tutorial
PHPPackagist · v1.0.0
composer require revaddress/usps-v3-php
Packagist ·GitHub · 59 tests · zero deps ·Magento Guide