Developers
Contents
On this page

Using the API

Rate limits and usage

Limits keep one integration from slowing down a business's desks.

The limits#

Every limit is counted over a minute, and every minute starts afresh.

Requests a minute
Counted perLimitCounts
Key, reading 600 Every GET the key makes
Key, writing 120 Every POST, PUT and PATCH the key makes
Business 1,200 Every request from all of the business's keys together
Address, failed sign-in 30 Requests from one IP address answered 401

A request counts against its key's tier and the business's at once, and the first one to run out refuses it. A refused request still counts — retrying in a tight loop keeps you refused.

For a sense of scale: a lobby screen reading four endpoints every five seconds makes 48 reads a minute. If you are near a limit, you are probably polling for something a webhook would tell you.

Rate limit headers#

Every answer to a key that was recognised carries three headers:

  • RateLimit-Limit — the limit of the tier nearest to running out;
  • RateLimit-Remaining — how many requests are left on it this minute;
  • RateLimit-Reset — seconds until the minute ends and it starts again.
A read, well inside its limit
HTTP/1.1 200 OK
RateLimit-Limit: 600
RateLimit-Remaining: 587
RateLimit-Reset: 41

Over a limit, the answer is 429, with Retry-After in seconds:

HTTP/1.1 429 Too Many Requests
RateLimit-Limit: 120
RateLimit-Remaining: 0
RateLimit-Reset: 17
Retry-After: 17
Response (429)
{
  "error": {
    "code": "TOO_MANY_REQUESTS",
    "message": "Too many requests for this API key. Wait and try again"
  }
}

Backing off#

  • On a 429, wait exactly Retry-After seconds, then try again. Waiting less is refused again.
  • Watch RateLimit-Remaining. When it is low, slow down before you are refused, not after.
  • Several workers sharing one key share its limit; give each job its own key instead.
  • Cache what changes slowly. Lines, services and desks change a few times a day; a visit changes a few times an hour. Ask for the first every few minutes, or when a webhook says so.
Honouring Retry-After

Node

async function withRetry(send) {
  for (let attempt = 1; ; attempt++) {
    const res = await send();
    if (res.status !== 429 || attempt === 5) return res;
    const wait = Number(res.headers.get("Retry-After") ?? "1");
    await new Promise((resolve) => setTimeout(resolve, wait * 1000));
  }
}

const res = await withRetry(() =>
  fetch("https://business.linemeup.in/api/v1/lines", {
    headers: { Authorization: `Bearer ${process.env.LINEMEUP_API_KEY}` },
  }),
);

Python

import os
import time

import requests

def with_retry(send, attempts=5):
    for attempt in range(1, attempts + 1):
        res = send()
        if res.status_code != 429 or attempt == attempts:
            return res
        time.sleep(int(res.headers.get("Retry-After", "1")))

res = with_retry(lambda: requests.get(
    "https://business.linemeup.in/api/v1/lines",
    headers={"Authorization": f"Bearer {os.environ['LINEMEUP_API_KEY']}"},
    timeout=10,
))

PHP

<?php
function with_retry(callable $send, int $attempts = 5): array
{
    for ($attempt = 1; ; $attempt++) {
        [$status, $headers, $body] = $send();
        if ($status !== 429 || $attempt === $attempts) {
            return [$status, $headers, $body];
        }
        sleep((int) ($headers['retry-after'] ?? 1));
    }
}

Reading your usage#

The owner sees how each key and each endpoint is being used in Settings → Integrations:

  • Per key — requests today and over the last 30 days, how many were errors and how many were refused for rate, the busiest endpoints, average and slowest time, and when it was last used.
  • Per webhook endpoint — deliveries that succeeded, failed or were given up, the success rate, the median and 95th-percentile time your receiver took, and the latest failures.
  • A chart of the last 30 days, requests and deliveries side by side.

Usage is counted by the business's own day and hour. Hourly figures are kept for 30 days and daily ones for 13 months. Figures can lag by up to half a minute.