Nanonets API enforces rate limits to ensure fair usage and maintain optimal performance for all users. Getting a 429 response code from our API means that you have reached our rate-limit.

The rate limit applies to all POST requests within the OCR Predict section, including:

  • Prediction for Image URL
  • Prediction for Image File
  • Async Prediction for Image URL
  • Async Prediction for Image File

What’s the difference between Sync Call and Async Call?

  1. Sync: Your files will get uploaded and processed, and you will see the results on the screen.
  2. Async: your files will get uploaded and processed at a later point in time (usually within 5 minutes). Recommended if you are processing a lot of large files (> 3 pages of PDFs)

With the rollout of rate limiting, customers who integrated with the Nanonets platform via API might start seeing a new HTTP error code 429 from the file processing APIs:

  • /api/v2/OCR/Model/<model_id>/LabelFile
  • /api/v2/OCR/Model/<model_id>/LabelUrls

This error is thrown when the rate limit threshold in a 1-minute window reaches the set rate limit per model.

Handling 429

When you receive a 429 Too Many Requests response, it indicates that you've hit the rate limit for your API calls within the last 1 minute. Here's how you can handle it:

  1. Implement a Backoff Strategy: Start with a 30-second delay before retrying the request.
  2. Use Exponential Backoff: If you continue to receive 429 responses, increase the delay exponentially (e.g., 30s, 60s, 120s, etc.).
  3. Monitor and Log: Track the occurrences of 429 responses to optimize your request patterns and avoid hitting the rate limit.

Sample Implementations

Python

import requests
import time

url = 'https://app.nanonets.com/api/v2/OCR/Model/REPLACE_MODEL_ID/LabelFile/'
data = {'file': open('REPLACE_IMAGE_PATH.jpg', 'rb')}
auth = requests.auth.HTTPBasicAuth('5a09c08f-50ec-11ee-8eb4-82b44427823b', '')

def send_request(data, delay=30):
    response = requests.post(url, auth=auth, files=data)
    if response.status_code == 429:
        print(f"Rate limit hit. Retrying after {delay} seconds.")
        time.sleep(delay)
        return send_request(data, delay * 2)  # Exponential backoff
    return response

response = send_request(data)
print(response.text)

Node.js

var request = require('request');
var fs = require('fs');

const form_data = {
    'modelId': 'REPLACE_MODEL_ID',
    'file': fs.createReadStream('REPLACE_IMAGE_PATH.jpg'),
};

const options = {
    url: 'https://app.nanonets.com/api/v2/OCR/Model/REPLACE_MODEL_ID/LabelFile/',
    formData: form_data,
    headers: {
        'Authorization': 'Basic ' + Buffer.from('5a09c08f-50ec-11ee-8eb4-82b44427823b' + ':').toString('base64')
    }
};

function sendRequest(options, delay = 30000) {
    request.post(options, function (err, httpResponse, body) {
        if (httpResponse && httpResponse.statusCode === 429) {
            console.log(`Rate limit hit. Retrying after ${delay / 1000} seconds.`);
            setTimeout(() => sendRequest(options, delay * 2), delay);  // Exponential backoff
        } else {
            console.log(body);
        }
    });
}

sendRequest(options);

JavaScript (Fetch API)

function sendRequest(delay = 30000) {
    var data = new FormData();
    data.append('file', fileBlob); // This is file object
    // data.append('base64_data', base64EncodedFile); // Can use this for base64 of the file

    var xhr = new XMLHttpRequest();

    xhr.addEventListener("readystatechange", function () {
        if (this.readyState === this.DONE) {
            if (this.status === 429) {
                console.log(`Rate limit hit. Retrying after ${delay / 1000} seconds.`);
                setTimeout(() => sendRequest(delay * 2), delay);  // Exponential backoff
            } else {
                console.log(this.responseText);
            }
        }
    });

    xhr.open("POST", "https://app.nanonets.com/api/v2/OCR/Model/{{model_id}}/LabelFile/");
    xhr.setRequestHeader("authorization", "Basic " + btoa("5a09c08f-50ec-11ee-8eb4-82b44427823b:"));

    xhr.send(data);
}

sendRequest();

Best Practices

  • Optimize Requests: Reduce the number of API calls by using asynchronous processing where possible.
  • Monitor Usage: Use logging and analytics to understand your usage patterns and adjust accordingly.
  • Graceful Handling: Ensure your application can handle rate limiting gracefully without significant disruptions to user experience.

Implement these strategies to effectively manage rate limits and ensure smooth integration with our API platform.