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 drop-in USPS v3 REST layer. Start with the free proof wedge — address validation, address extract, ZIP+4, city/state lookup, and rates — then expand into label workflows, managed tracking routes, BYOK, and request-access pickup when you are ready.

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

Use the free tier to prove the integration with live USPS-backed responses before you commit to protected workflow access. No API key required.

API key required
  • Tracking route access
  • Labels + batch validation
  • Dashboard + BYOK
  • Pickup request access

Protected workflows unlock after signup and plan/account setup, with public claim depth still gated by route-specific proof.

Higher-volume access
  • Managed throughput
  • Enterprise onboarding
  • Licensing-dependent workflows

Use account setup and support when label volume, routing depth, or licensing needs exceed the default path.

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 drop-in USPS v3 REST layer. Start with the free proof wedge — address validation, address extract, ZIP+4, city/state lookup, and rates — then expand into label workflows, managed tracking routes, BYOK, and request-access pickup when you are ready.

// 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.

Method Endpoint Auth Plan
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.

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