Skip to main content

Rate Limits

All API requests are rate limited per organization to ensure fair usage and platform stability.

Default Limits

WindowLimit
Per minute60 requests
Per day5,000 requests
Per-organization overrides are available on enterprise plans. Contact support@dealmachine.com to discuss higher limits.

Response Headers

Every API response includes rate limit headers so you can track your usage in real time:
HeaderDescription
X-RateLimit-LimitMaximum requests allowed per minute
X-RateLimit-RemainingRequests remaining in the current minute window
X-RateLimit-ResetUnix timestamp (seconds) when the minute window resets
X-RateLimit-Day-LimitMaximum requests allowed per day
X-RateLimit-Day-RemainingRequests remaining today

429 Response

When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please retry after the specified time.",
    "request_id": "req_abc123def456",
    "details": {
      "limit_type": "minute",
      "retry_after": 12
    }
  }
}
The response also includes a Retry-After header with the number of seconds to wait before retrying.
FieldDescription
details.limit_typeWhich limit was exceeded: minute or day
details.retry_afterSeconds until you can retry
Retry-After headerSame value as details.retry_after

Exponential Backoff

When you receive a 429 or 5xx response, use exponential backoff to retry. This means waiting progressively longer between retries:
  1. Wait 1 second, then retry
  2. If still failing, wait 2 seconds, then retry
  3. Then 4 seconds, 8 seconds, 16 seconds
  4. Cap the maximum wait at 30 seconds
Add a small random jitter (0-500ms) to each wait to prevent thundering herd problems when multiple clients retry simultaneously.

JavaScript / TypeScript

async function fetchWithRetry(
  url: string,
  options: RequestInit,
  maxRetries = 5
): Promise<Response> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.ok) return response;

    // Don't retry client errors (except 429)
    if (response.status >= 400 && response.status < 500 && response.status !== 429) {
      return response;
    }

    if (attempt === maxRetries) return response;

    // Exponential backoff with jitter, capped at 30s
    const baseDelay = Math.min(1000 * Math.pow(2, attempt), 30000);
    const jitter = Math.random() * 500;
    await new Promise((resolve) => setTimeout(resolve, baseDelay + jitter));
  }

  throw new Error("Unreachable");
}

// Usage
const response = await fetchWithRetry(
  "https://api.v2.dealmachine.com/v1/enrichment/address",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      addresses: [{ full_address: "123 Main St, Austin, TX 78704" }],
    }),
  }
);

Python

import time
import random
import requests

def fetch_with_retry(url, headers, json_body, max_retries=5):
    for attempt in range(max_retries + 1):
        response = requests.post(url, headers=headers, json=json_body)

        if response.ok:
            return response

        # Don't retry client errors (except 429)
        if 400 <= response.status_code < 500 and response.status_code != 429:
            return response

        if attempt == max_retries:
            return response

        # Exponential backoff with jitter, capped at 30s
        base_delay = min(2 ** attempt, 30)
        jitter = random.uniform(0, 0.5)
        time.sleep(base_delay + jitter)

# Usage
response = fetch_with_retry(
    "https://api.v2.dealmachine.com/v1/enrichment/address",
    headers={"Authorization": f"Bearer {api_key}"},
    json_body={
        "addresses": [{"full_address": "123 Main St, Austin, TX 78704"}]
    },
)

Best Practices

DoDon’t
Retry 429 and 5xx responses with exponential backoffRetry 400 or 401 errors (fix the request instead)
Check X-RateLimit-Remaining before sending burstsIgnore rate limit headers and retry blindly
Use batch endpoints to reduce request countSend one item per request when batch is available
Cache results locally when possibleRe-fetch data you already have
Add jitter to retry delaysHave all clients retry at the exact same time
All enrichment and batch endpoints accept up to 250 items per request. Batching reduces your request count significantly — 250 addresses in a single request counts as 1 request toward your rate limit.