Rate Limits

To keep the Shipwell API fast and reliable for every customer, the API limits how many requests a company can send per minute to each area of the API. Most integrations never come close to these limits. This page explains how they work, what your integration sees when it reaches one, and how to stay well within them.

How rate limits work

  • Limits apply per API area. Each area of the API, such as Shipments or Rating, has its own allowance. Using one area never reduces what is available in another.
  • Counted per minute. Each allowance starts fresh at the top of every clock minute (:00 seconds). If you reach a per-minute limit, you wait at most until the next minute starts. Companies on a plan also have an hourly limit, which starts fresh at the top of every hour.
  • Shared across your company. The allowance belongs to your company, not to a user or token. All users, tokens and integrations of your company share it.
  • Sandbox and production are separate. Traffic in sandbox never counts against your production allowance.
  • Authentication isn't counted. Requests to authenticate, such as /v2/auth/token/ , do not count against any limit.

Plans

Every company starts on the standard limits, which differ by API area. Until your company is on a plan or has a raised limit, the X-RateLimit-Limit header on any response from an area shows its standard limit (see What your integration sees). A plan raises the limits on every API area at once, as a multiple of the standard limits:

Plan Per-minute limits Hourly limits Included API calls per month
Bronze 2 × the standard limits 30 × the per-minute limit 2 million
Silver 4 × the standard limits 30 × the per-minute limit 6 million
Gold 6 × the standard limits 30 × the per-minute limit 20 million
Enterprise Set per API area for your company Set for your company Agreed with your company
  • The monthly allowance never blocks a request. If your company goes past it, your Shipwell representative will talk with you about the plan that fits.
  • Your limits are always in the headers. X-RateLimit-Limit shows your company's current limit for each API area, whatever your plan.
  • One busy area doesn't need a bigger plan. Shipwell can raise a single API area on any plan. See Need a higher limit?

To change plans, contact your Shipwell representative.

What your integration sees

Every response from a rate-limited area tells you where you stand:

Header Meaning
X-RateLimit-Limit Your company's limit for this API area
X-RateLimit-Remaining Requests you have left before that limit
X-RateLimit-Reset Seconds until the allowance starts fresh

With both a per-minute and an hourly limit, the headers describe whichever one you're closer to.

When an area's limit is reached, further requests to that area receive 429 Too Many Requests until the allowance starts fresh. A 429 request was not processed, so it is always safe to send the same request again.

Example responses
httphttp
Copy
Copied
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 842
X-RateLimit-Reset: 23
Copy
Copied
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 23
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 23

{"error": "rate_limit_exceeded"}

What your team should do

  • Handle 429 responses. Wait the number of seconds in the Retry-After header, then send the same request again. Don't retry immediately in a loop: every retry before the minute resets gets another 429 .
  • Add a little randomness to retries. If several workers run in parallel, add a short random delay (for example 0–2 seconds) so they don't all retry at the same instant.
  • Pace bulk jobs. For backfills, syncs and scheduled jobs, watch X-RateLimit-Remaining and slow down as it approaches 0.
Example: retry after a 429
pythonjavascript
Copy
Copied
import random
import time

import requests


def send(method, url, **kwargs):
    while True:
        response = requests.request(method, url, **kwargs)
        if response.status_code != 429:
            return response
        wait = int(response.headers.get("Retry-After", "1"))
        time.sleep(wait + random.uniform(0, 2))
Copy
Copied
async function send(url, options = {}) {
  while (true) {
    const response = await fetch(url, options);
    if (response.status !== 429) {
      return response;
    }
    const wait = Number(response.headers.get("Retry-After") ?? 1);
    await new Promise((resolve) => setTimeout(resolve, (wait + Math.random() * 2) * 1000));
  }
}
File uploads

These examples send the same request again. For JSON bodies that just works. When uploading a file, open the file again (or rewind it) before each retry, otherwise the retry can send an empty file.

Need a higher limit?

If your integration legitimately needs more than its current limit, contact your Shipwell representative or support@shipwell.com. Tell us which API area, what volume you expect per minute, and what the traffic is for. Shipwell reviews the request and can raise the limit for your company. A raised limit applies to that API area only.

Copyright © Shipwell 2025. All right reserved.