Getting Started Rate Limits

Rate Limits

Logimeter enforces rate limits to protect service reliability for all partners. This page explains the limits that apply to your token, what happens when you exceed them, and how to write resilient code that handles throttling gracefully.

Overview

Rate limits are applied per API token on a rolling per-minute window. Every request you make consumes capacity from that window. Once the limit is reached, the API returns a 429 Too Many Requests response until the window resets.

The limits listed below are approximate guidelines. If your integration consistently approaches these thresholds, contact support@logimeter.com to discuss your use case — higher limits may be available for specific patterns.

Current limits

Endpoint group Limit Notes
All endpoints 600 req / min Applies to all /v1/, /v2/, and /api/internal/ partner API endpoints. Cache your token and avoid unnecessary repeated requests.

Rate limit headers

When your request rate is approaching the limit, or after a throttled request, Logimeter includes informational headers in the response so your code can adapt:

Rate limit response headers
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 412
X-RateLimit-Reset: 1705312800
Header Type Description
X-RateLimit-Limit integer The total number of requests allowed per minute for this endpoint group.
X-RateLimit-Remaining integer The number of requests you can still make in the current window before being throttled.
X-RateLimit-Reset integer Unix timestamp (UTC) at which the current rate limit window resets and your full quota is restored.

On a throttled response (HTTP 429), the standard Retry-After header is also present, giving the number of seconds to wait before retrying:

Additional header on 429 responses
Retry-After: 3

429 Too Many Requests

When you exceed your rate limit, the API returns HTTP 429 with the following JSON body:

429 Too Many Requests
{
  "detail": "Request was throttled. Expected available in 3 seconds."
}

The message embeds the number of seconds until the window resets. Parse this from the Retry-After header rather than the message body, since the body text is not guaranteed to remain stable.

Best practices

Designing within the limits — most integrations never approach the 600 req/min ceiling if they follow a few simple patterns.
  • Cache your token. Re-authenticating on every request is the most common avoidable cause of 429s on the auth endpoint. Obtain a token once at startup, store it in memory, and reuse it for all subsequent calls. Tokens do not expire unless rotated by support.
  • Read pages sequentially, not in parallel. For bulk data syncs, iterate pages one at a time using the next URL. Firing multiple page requests concurrently multiplies your per-second rate and can trigger throttling even when the per-minute total would be acceptable.
  • Use webhooks and callbacks instead of polling. If you are building a real-time integration that watches for call events or lead status changes, configure a callback URL (see Webhooks & Callbacks) rather than polling an endpoint on a tight loop.
  • Retire DNA numbers promptly. Issuing DELETE requests to retire Dynamic Number Allocation sessions as soon as a visitor leaves clears your allocated inventory and prevents a backlog of cleanup requests hitting the API simultaneously at the end of a session batch.
  • Implement exponential backoff on 429. When a throttled response occurs, wait at least the number of seconds specified in Retry-After before retrying, and increase the wait time exponentially on subsequent failures. See the example below.
  • Monitor X-RateLimit-Remaining. If your code sees this value drop close to zero, introduce a brief pause before the next request rather than waiting for a 429 to occur.

Retry with exponential backoff

The function below wraps any requests call with automatic retry logic. It honours the Retry-After header on 429 responses and falls back to exponential backoff (1 s, 2 s, 4 s) on transient server errors:

import requests
import time

def api_call_with_retry(session, method, url, max_attempts=3, **kwargs):
    """
    Call a Logimeter API endpoint, retrying automatically on 429 or 5xx.

    :param session:       A requests.Session with the Authorization header set.
    :param method:        HTTP method string, e.g. 'GET' or 'POST'.
    :param url:           Full URL of the endpoint.
    :param max_attempts:  Maximum number of total attempts before raising.
    :param **kwargs:      Passed through to session.request (json=, params=, etc.)
    :returns:             The successful requests.Response object.
    :raises Exception:    When all attempts are exhausted.
    """
    for attempt in range(max_attempts):
        resp = session.request(method, url, **kwargs)

        if resp.status_code == 429:
            # Honour Retry-After; fall back to exponential backoff
            wait = int(resp.headers.get('Retry-After', 2 ** attempt))
            print(f'Rate limited. Waiting {wait}s before retry {attempt + 1}/{max_attempts}.')
            time.sleep(wait)
            continue

        if resp.status_code >= 500 and attempt < max_attempts - 1:
            # Brief backoff on transient server errors
            wait = 2 ** attempt
            print(f'Server error {resp.status_code}. Waiting {wait}s.')
            time.sleep(wait)
            continue

        # Any other response (success or client error) — return immediately
        return resp

    raise Exception(f'API call to {url} failed after {max_attempts} attempts')


# Usage
import requests

session = requests.Session()
session.headers['Authorization'] = 'Token YOUR_TOKEN'

resp = api_call_with_retry(session, 'GET', 'https://next.logimeter.com/v2/contact/')
contacts = resp.json()
print(f"Fetched {contacts['count']} contacts")
/**
 * Call a Logimeter API endpoint, retrying automatically on 429 or 5xx.
 *
 * @param {string} method        - HTTP method, e.g. 'GET' or 'POST'
 * @param {string} url           - Full endpoint URL
 * @param {object} options       - fetch() options (headers, body, etc.)
 * @param {number} maxAttempts   - Maximum attempts before throwing
 * @returns {Promise<Response>}  - The successful Response object
 */
async function apiCallWithRetry(method, url, options = {}, maxAttempts = 3) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const resp = await fetch(url, { method, ...options });

    if (resp.status === 429) {
      const retryAfter = parseInt(resp.headers.get('Retry-After') ?? String(2 ** attempt), 10);
      console.warn(`Rate limited. Waiting ${retryAfter}s (attempt ${attempt + 1}/${maxAttempts}).`);
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      continue;
    }

    if (resp.status >= 500 && attempt < maxAttempts - 1) {
      const wait = 2 ** attempt;
      console.warn(`Server error ${resp.status}. Waiting ${wait}s.`);
      await new Promise(resolve => setTimeout(resolve, wait * 1000));
      continue;
    }

    return resp; // success or client error — return to caller
  }

  throw new Error(`API call to ${url} failed after ${maxAttempts} attempts`);
}

// Usage
const TOKEN = 'YOUR_TOKEN';
const headers = { 'Authorization': `Token ${TOKEN}` };

const resp = await apiCallWithRetry('GET', 'https://next.logimeter.com/v2/contact/', { headers });
const contacts = await resp.json();
console.log('Total contacts:', contacts.count);

Frequently asked questions

Are rate limits shared across multiple tokens on the same account?

No. Each API token has its own independent rate limit bucket. If your account has multiple tokens (for example, one per integration service), each token's requests are counted separately.

Does retrying a failed request count against my limit?

Yes — every HTTP request consumes capacity regardless of whether it succeeds. This is why it is important to wait for the full Retry-After window before retrying after a 429, rather than immediately looping.

My integration needs more than 600 requests per minute. What can I do?

Contact support@logimeter.com with a description of your use case and expected peak request rate. In many cases the same goal can be achieved within the existing limit by using webhooks instead of polling, or by batching operations. For genuinely high-volume integrations, elevated limits may be available.

Do GET requests and POST requests count the same?

Yes. All HTTP methods (GET, POST, PUT, PATCH, DELETE) consume rate limit capacity equally, with the only distinction being the endpoint group (auth vs. all others).