❗ Rate Limiting

The Apicbase API implements a rate limiting strategy to ensure stability and provide good service to all API users. The current limit is set to 100 requests per minute for all users, including trial and full customers as well as third-party partners, for both read and write operations. If your application exceeds this limit, the server will respond with a 429 Too Many Requests status code.

This problem often arises when accessing GET endpoints (such as the Get Recipes endpoint) in quick succession. The rate limit of 100 requests per minute is sufficient for all intended uses of the Apicbase API, but clients using the API in unintended ways will likely exceed this limit rapidly.

❗️

The Apicbase API should not be used as a live API.

Using the Apicbase API as a live API is a common reason for surpassing these rate limits. Real-time data for ingredients, recipes, and other entities should not be served using the Apicbase API. If you have a customer-facing application that displays recipe data, for example, your application should not generate an API request every time a user clicks a recipe. Instead, you should cache this data in a local database and serve it to your users, updating the cache as necessary.

Avoidance strategies

To ensure that your application does not exceed the established rate limits and to improve the experience for your users, it is recommended to implement strategies that reduce the number of redundant API requests.

Redundant requests refer to those that fetch data that has not changed since the previous request. This reduces the overhead generated by waiting for Apicbase to compile the data, and helps in providing better performance to your users.

We strongly recommend setting up a script that periodically looks for changed data, and using the modified_date__gt filter available on most list GET endpoints to filter on items that changed since the last sync.

RateLimit headers

The Apicbase API provides Rate Limiter Headers on every response from an endpoint that is bound by the rate limiter to help API consumers gracefully handle rate limiting and avoid errors caused by exceeding it:

HeaderDescription
X-RateLimit-LimitRequest limit per minute for the current endpoint (usually 100/minute)
X-RateLimit-RemainingThe number of requests left for the current one minute rolling window
X-RateLimit-WaitWhen the client is rate limited, this header says how many seconds it must wait until the next request

In case a violation of the limit incurs and a 429 Too Many Requests error response is received, the API client can retrieve from the X-RateLimit-Wait header of the 429 response the amount of seconds it must wait before making the next request, in order to prevent further 429 responses.

The following script demonstrates a routine that runs in a loop to retrieve data from the /xyz endpoint while using the rate limit headers to stay within the limits set by the Apicbase API. This routine showcases the utilization of both the X-RateLimit-Remaining and X-RateLimit-Wait headers:

import requests
import time

# Set up API authentication
access_token = 'your_access_token'
headers = {'Authorization': f'Bearer {access_token}'}

# Define API endpoint
api_url = 'https://api.apicbase.com/api/v2/xyz'

while True:
    # Set a default value of 1 for requests_left
    requests_left = 1
    
    # Keep making requests until we hit the rate limit
    while requests_left > 0:
        # Make the request
        response = requests.get(api_url, headers=headers)
        
        # Check the rate limit headers to see how many requests are left
        requests_left = int(response.headers['X-RateLimit-Remaining'])
        
        # Do something with the response (replace with your actual code)
        do_something_with_response(response)
        
    # If we've hit the rate limit, wait for the specified amount of time
    wait_time = int(response.headers['X-RateLimit-Wait'])
    time.sleep(wait_time)

async function makeApiRequests() {
  while (true) {
    let requestsLeft = 1;
    
    while (requestsLeft > 0) {
      const response = await fetch('https://api.apicbase.com/api/v2/xyz');
      requestsLeft = response.headers.get('X-RateLimit-Remaining');
      await doSomethingWithResponse(response);
    }
    
    const waitTime = response.headers.get('X-RateLimit-Wait');
    await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
  }
}

async function doSomethingWithResponse(response) {
  // Replace with your own code to handle the response
  const data = await response.json();
  console.log(data);
}

makeApiRequests();

<?php
while (true) {
    $requests_left = 1;
    while ($requests_left > 0) {
        $response = file_get_contents('https://api.apicbase.com/api/v2/xyz', false, stream_context_create([
            'http' => [
                'method' => 'GET',
                'header' => 'Authorization: Bearer your-api-token'
            ]
        ]));
        $requests_left = intval(explode(';', $http_response_header[6])[0]);
        do_something_with_response($response);
    }
    $wait_time = intval(explode(';', $http_response_header[6])[1]);
    sleep($wait_time);
}

using System;
using System.Net;
using System.Threading;

class Program {
    static void Main(string[] args) {
        while (true) {
            int requestsLeft = 1;
            while (requestsLeft > 0) {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.apicbase.com/api/v2/xyz");
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                requestsLeft = int.Parse(response.Headers["X-RateLimit-Remaining"]);
                DoSomethingWithResponse(response);
            }
            int waitTime = int.Parse(response.Headers["X-RateLimit-Wait"]);
            Thread.Sleep(waitTime * 1000);
        }
    }

    static void DoSomethingWith(HttpWebResponse response) {
        // Code to handle the response goes here
    }
}