Developers
Menu: Rate limits and quotas

Rate limits and quotas

Two limits apply to your account. Both are shared by all of your account's keys.

Limit Applies to Default Resets
Rate limit Every request Live: set per account, usually 60 a minute. Sandbox: 120 a minute Every minute
Monthly quota Successful live score lookups Set per account in your agreement 1st of each month, 00:00 UTC

A score lookup counts against the monthly quota only when it returns a score. Errors, GET /v1/usage, GET /v1/health and all sandbox requests are free.

GET /v1/usage returns your current limits and how much of the quota is used.

Headers on every response#

Header Description
X-RateLimit-Limit Requests allowed per minute
X-RateLimit-Remaining Requests left in the current minute
X-RateLimit-Reset Unix time when the current minute's window resets
X-Quota-Limit Live only: score lookups allowed this month
X-Quota-Remaining Live only: score lookups left this month

Watch X-Quota-Remaining to warn your team before the quota runs out, rather than finding out from a refusal.

When you hit a limit#

Both limits answer 429 with a rate_limit_error:

  • rate_limit_exceeded: wait the number of seconds in the Retry-After header, then retry.
  • monthly_quota_exceeded: do not retry. Lookups are refused until the 1st, or until your quota is raised.

Retrying well#

Retry on 429 rate_limit_exceeded and on 503 or 500. Do not retry other errors; they will fail the same way again.

async function getDtScore(dot, attempt = 0) {
  const response = await fetch(
    `https://api.dollartraq.com/v1/dt-score?dot_number=${dot}`,
    { headers: { Authorization: `Bearer ${process.env.DT_SCORE_KEY}` } }
  );
  if (response.ok) return response.json();

  const { error } = await response.json();
  const retryable = response.status >= 500 || error.code === "rate_limit_exceeded";
  if (!retryable || attempt >= 4) throw new Error(`${error.code}: ${error.message}`);

  const retryAfter = Number(response.headers.get("Retry-After")) || 1;
  const wait = Math.max(retryAfter, 2 ** attempt) * 1000 + Math.random() * 250;
  await new Promise((resolve) => setTimeout(resolve, wait));
  return getDtScore(dot, attempt + 1);
}
import os, random, time, requests

def get_dt_score(dot, attempts=5):
    for attempt in range(attempts):
        response = requests.get(
            "https://api.dollartraq.com/v1/dt-score",
            params={"dot_number": dot},
            headers={"Authorization": f"Bearer {os.environ['DT_SCORE_KEY']}"},
            timeout=30,
        )
        if response.ok:
            return response.json()

        error = response.json()["error"]
        retryable = response.status_code >= 500 or error["code"] == "rate_limit_exceeded"
        if not retryable or attempt == attempts - 1:
            raise RuntimeError(f"{error['code']}: {error['message']}")

        retry_after = int(response.headers.get("Retry-After", 1))
        time.sleep(max(retry_after, 2 ** attempt) + random.random() / 4)

Keep request volume down#

  • Scores change at most daily. If you show the same carrier many times a day, keep its score for a few hours instead of asking again.
  • Look a carrier up when it matters, such as at onboarding and before a tender, rather than on every page view.
  • If you need a higher limit or quota, ask your DollarTraq contact.

Questions about an integration? Email support@dollartraq.com and quote the request_id from the response.

© 2026 DollarTraq. Scores are calculated from public FMCSA data and are a decision aid, not a guarantee of a carrier's performance.