Developer Dashboard

AvalAI API Rate Limits and Account Tiers

This guide explains AvalAI API rate limits, account tiers, and how phone verification unlocks higher limits plus up to 200,000 Tomans of free signup credit.

Understanding Rate Limits

Rate limits are restrictions on the number of API requests you can make within a certain time period. These limits are in place to ensure fair usage of the API and to prevent abuse. AvalAI implements rate limits similar to OpenAI's approach, with automatic tier upgrades based on your usage.

Understanding Usage Tiers

AvalAI uses a tier-based system where your rate limits grow automatically as your account matures — first by verifying your phone, then through cumulative top-ups. There are no applications, no waiting periods, and no manual approvals: as soon as you meet the requirements for a tier, your new limits are active.

How Rate Limits Work

Rate limits are measured in five ways:

  • RPM (requests per minute)
  • RPD (requests per day)
  • TPM (tokens per minute)
  • TPD (tokens per day)
  • IPM (images per minute)

You can hit rate limits across any of these metrics, depending on which is reached first. For example, you might send 20 requests with only 100 tokens and hit your RPM limit, even if you haven't reached your TPM limit.

Tier Qualification

Every registered AvalAI user can call the API right away. Your tier is decided by two things:

  1. How you verified your account — email-only, or with a phone number.
  2. How much you've topped up over time — top-ups are cumulative across your account's lifetime.
TierHow to QualifyFree Signup CreditRate Limits
Basic (Tier 0)Sign up with email only25,000 TomansSee Basic Tier Rate Limits
Tier 1Register with a phone or connect and verify one later200,000 Tomans totalSee Tier 1 Rate Limits
Tier 2$10 total topped upSignup credit remains available until usedSee Tier 2 Rate Limits
Tier 3$50 total topped upSignup credit remains available until usedSee Tier 3 Rate Limits
Tier 4$250 total topped upSignup credit remains available until usedSee Tier 4 Rate Limits
Tier 5$1,000 total topped upSignup credit remains available until usedSee Tier 5 Rate Limits

Good to know:

  • 🎁 Register with a verified phone and receive 200,000 Tomans of free API credit. No top-up is required.
  • ✉️ Starting with email is supported. Email-only registration receives 25,000 Tomans immediately on the Basic tier.
  • 📱 Add and verify a phone later to receive 175,000 more Tomans. This brings the email-first account to the same 200,000-Toman total and instantly upgrades it to Tier 1. The phone bonus tops the total up to 200,000 Tomans; it is not an extra 200,000 on top of the email credit.
  • Tier upgrades happen automatically and instantly the moment you meet the next requirement — no support tickets, no waiting.
  • 💳 Top-ups are cumulative. Tiers 2 and above are based on your total historical top-up amount, not your current balance, and none of your credit is consumed by upgrading — every penny stays available for API usage.
  • 💱 Top-ups are made in IRT; the USD equivalent for tier qualification is calculated using the exchange rate shown on chat.avalai.ir/platform.
  • 📈 No monthly spending caps — you can use your full credit balance whenever you need to.
  • 🤖 Each tier unlocks more models and higher per-model limits. Rate limits are defined per model at the organization level.

For detailed rate limits for each model in your tier, visit the tier-specific pages linked above.

User API (/user/v1) Rate Limits

The /user/v1 endpoints have the following per-user request limits. The limit for your current account tier applies across these endpoints.

Account TierRequest Limit
Basic (Tier 0)3 requests per minute
Tier 115 requests per minute
Tier 250 requests per minute
Tier 3150 requests per minute
Tier 4350 requests per minute
Tier 5750 requests per minute

For endpoint details, see the User API reference.

Rate Limit Headers

When you make API requests, the response headers include information about your current rate limit status:

HeaderDescription
x-ratelimit-limit-requestsThe maximum number of requests allowed in the current time window
x-ratelimit-remaining-requestsThe number of requests remaining in the current time window
x-ratelimit-reset-requestsThe time at which the current rate limit window resets
x-ratelimit-limit-tokensThe maximum number of tokens allowed in the current time window
x-ratelimit-remaining-tokensThe number of tokens remaining in the current time window
x-ratelimit-reset-tokensThe time at which the token rate limit window resets

Handling Rate Limit Errors

When you exceed a rate limit, the API returns a 429 Too Many Requests status code along with information about when you can retry:

json
{
  "error": {
    "message": "Rate limit exceeded for requests. Please try again in 30s.",
    "type": "rate_limit_error",
    "param": null,
    "code": "rate_limit_exceeded"
  }
}

The response may include a Retry-After header indicating the number of seconds to wait before retrying:

Retry-After: 30

Best Practices for Managing Rate Limits

Implement Exponential Backoff

When you encounter a rate limit error, use exponential backoff to retry the request:

Chat Completions example

python
import os
import random
import time
from openai import OpenAI, RateLimitError

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)


def with_backoff(call, max_retries=5, initial_delay=1, max_delay=60):
    delay = initial_delay
    for attempt in range(max_retries + 1):
        try:
            return call()
        except RateLimitError as error:
            if attempt == max_retries:
                raise
            retry_after = (
                int(error.headers.get("retry-after", 0)) if error.headers else 0
            )
            delay = max(delay, retry_after)
            sleep_time = delay + random.uniform(0, delay * 0.5)
            print(f"Rate limit exceeded. Retrying in {sleep_time:.2f}s...")
            time.sleep(sleep_time)
            delay = min(delay * 2, max_delay)


completion = with_backoff(
    lambda: client.chat.completions.create(
        model="gpt-5.5",
        messages=[{"role": "user", "content": "Hello!"}],
    )
)

print(completion.choices[0].message.content)
javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,
  baseURL: "https://api.avalai.ir/v1",
});

async function withBackoff(call, maxRetries = 5, initialDelay = 1000, maxDelay = 60000) {
  let delay = initialDelay;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await call();
    } catch (error) {
      if (error.status !== 429 || attempt === maxRetries) throw error;

      const retryAfter = error.headers?.["retry-after"]
        ? Number(error.headers["retry-after"]) * 1000
        : 0;
      delay = Math.max(delay, retryAfter);
      const sleepTime = delay + Math.random() * delay * 0.5;
      console.log(`Rate limit exceeded. Retrying in ${sleepTime / 1000}s...`);
      await new Promise((resolve) => setTimeout(resolve, sleepTime));
      delay = Math.min(delay * 2, maxDelay);
    }
  }
}

const completion = await withBackoff(() =>
  client.chat.completions.create({
    model: "gpt-5.5",
    messages: [{ role: "user", content: "Hello!" }],
  }),
);

console.log(completion.choices[0].message.content);
bash
#!/usr/bin/env bash
set -euo pipefail

payload='{"model":"gpt-5.5","messages":[{"role":"user","content":"Hello!"}]}'
delay=1

for attempt in 0 1 2 3 4 5; do
  response=$(curl -sS -w "\n%{http_code}" https://api.avalai.ir/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $AVALAI_API_KEY" \
    -d "$payload")
  status="${response##*$'\n'}"
  body="${response%$'\n'*}"

  if [[ $status == "200" ]]; then
    echo "$body"
    break
  fi

  if [[ $status != "429" || $attempt == "5" ]]; then
    echo "$body" >&2
    exit 1
  fi

  echo "Rate limit exceeded. Retrying in ${delay}s..." >&2
  sleep "$delay"
  delay=$((delay * 2 > 60 ? 60 : delay * 2))
done

Responses API equivalent

Use the same retry pattern with /v1/responses; messages becomes input, and final text is read from response.output_text.

python
response = with_backoff(
    lambda: client.responses.create(
        model="gpt-5.5",
        input="Hello!",
    )
)

print(response.output_text)
javascript
const response = await withBackoff(() =>
  client.responses.create({
    model: "gpt-5.5",
    input: "Hello!",
  }),
);

console.log(response.output_text);
bash
#!/usr/bin/env bash
set -euo pipefail

payload='{"model":"gpt-5.5","input":"Hello!"}'
delay=1

for attempt in 0 1 2 3 4 5; do
  response=$(curl -sS -w "\n%{http_code}" https://api.avalai.ir/v1/responses \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $AVALAI_API_KEY" \
    -d "$payload")
  status="${response##*$'\n'}"
  body="${response%$'\n'*}"

  if [[ $status == "200" ]]; then
    echo "$body"
    break
  fi

  if [[ $status != "429" || $attempt == "5" ]]; then
    echo "$body" >&2
    exit 1
  fi

  echo "Rate limit exceeded. Retrying in ${delay}s..." >&2
  sleep "$delay"
  delay=$((delay * 2 > 60 ? 60 : delay * 2))
done

Implement Rate Limiting on Your Side

Proactively limit your request rate to avoid hitting the API's rate limits:

Python Example with Token Bucket Algorithm

python
import json
import logging
import os
from openai import OpenAI, APIError

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[logging.FileHandler("api_errors.log"), logging.StreamHandler()],
)
logger = logging.getLogger("avalai_api")

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)


def log_api_request(method, endpoint, params, response=None, error=None):
    """Log API request details."""
    # Create a copy of params to avoid modifying the original
    # And handle potential serialization issues with complex objects
    safe_params = {}
    try:
        for key, value in params.items():
            if key in {"messages", "input"} and isinstance(value, list):
                safe_params[key] = f"[{len(value)} items]"
            else:
                safe_params[key] = value
    except (AttributeError, TypeError):
        safe_params = str(params)

    log_data = {
        "method": method,
        "endpoint": endpoint,
        "params": safe_params,
    }

    if response:
        log_data["status_code"] = 200
        log_data["response_id"] = getattr(response, "id", None)
        try:
            logger.info(f"API Request Successful: {json.dumps(log_data)}")
        except TypeError:
            # Handle non-serializable objects
            log_data["params"] = str(safe_params)
            logger.info(f"API Request Successful: {json.dumps(log_data)}")

    if error:
        log_data["error_type"] = getattr(error, "type", type(error).__name__)
        log_data["error_message"] = str(error)
        log_data["status_code"] = getattr(error, "status_code", None)
        try:
            logger.error(f"API Request Failed: {json.dumps(log_data)}")
        except TypeError:
            # Handle non-serializable objects
            log_data["params"] = str(safe_params)
            logger.error(f"API Request Failed: {json.dumps(log_data)}")


# Chat Completions example
params = {"model": "gpt-5.5", "messages": [{"role": "user", "content": "Hello!"}]}

try:
    response = client.chat.completions.create(**params)
    log_api_request("POST", "/chat/completions", params, response=response)
    print(response.choices[0].message.content)
except APIError as e:
    log_api_request("POST", "/chat/completions", params, error=e)
    raise

# Responses API equivalent
response_params = {"model": "gpt-5.5", "input": "Hello!"}

try:
    response = client.responses.create(**response_params)
    log_api_request("POST", "/responses", response_params, response=response)
    print(response.output_text)
except APIError as e:
    log_api_request("POST", "/responses", response_params, error=e)
    raise

Batch Requests When Possible

For operations like embeddings, batch multiple inputs in a single request:

python
# Instead of making 10 separate requests
texts = [
    "The quick brown fox jumps over the lazy dog.",
    "The five boxing wizards jump quickly.",
    # ... 8 more texts
]

# Make a single batch request
response = client.embeddings.create(model="text-embedding-3-small", input=texts)

# Process all embeddings at once
embeddings = [item.embedding for item in response.data]

Monitor Your Usage

Track your API usage to avoid unexpected rate limit errors:

python
def track_usage(response):
    """Track API usage from response headers."""
    headers = response.headers

    # Request-based rate limits
    requests_limit = int(headers.get("x-ratelimit-limit-requests", 0))
    requests_remaining = int(headers.get("x-ratelimit-remaining-requests", 0))
    requests_reset = int(headers.get("x-ratelimit-reset-requests", 0))

    # Token-based rate limits
    tokens_limit = int(headers.get("x-ratelimit-limit-tokens", 0))
    tokens_remaining = int(headers.get("x-ratelimit-remaining-tokens", 0))
    tokens_reset = int(headers.get("x-ratelimit-reset-tokens", 0))

    # Calculate usage percentages
    requests_usage_pct = (
        100 - (requests_remaining / requests_limit * 100) if requests_limit else 0
    )
    tokens_usage_pct = (
        100 - (tokens_remaining / tokens_limit * 100) if tokens_limit else 0
    )

    print(
        f"Requests: {requests_remaining}/{requests_limit} ({requests_usage_pct:.1f}% used)"
    )
    print(f"Tokens: {tokens_remaining}/{tokens_limit} ({tokens_usage_pct:.1f}% used)")

    # Alert if usage is high
    if requests_usage_pct > 80 or tokens_usage_pct > 80:
        print("WARNING: API usage is high!")

    return {
        "requests": {
            "limit": requests_limit,
            "remaining": requests_remaining,
            "reset": requests_reset,
            "usage_pct": requests_usage_pct,
        },
        "tokens": {
            "limit": tokens_limit,
            "remaining": tokens_remaining,
            "reset": tokens_reset,
            "usage_pct": tokens_usage_pct,
        },
    }


# Chat Completions example
raw_response = client.chat.completions.with_raw_response.create(
    model="gpt-5.5", messages=[{"role": "user", "content": "Hello!"}]
)
completion = raw_response.parse()
usage_stats = track_usage(raw_response)
print(completion.choices[0].message.content)

# Responses API equivalent
raw_response = client.responses.with_raw_response.create(
    model="gpt-5.5", input="Hello!"
)
response = raw_response.parse()
usage_stats = track_usage(raw_response)
print(response.output_text)

Implement Request Queuing

For high-volume applications, implement a request queue:

python
import os
import queue
import threading
import time
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)

request_queue = queue.Queue()


def process_queue():
    """Process queued requests at a controlled rate."""
    requests_per_minute = 60  # Adjust for your tier
    request_interval = 60 / requests_per_minute

    while True:
        request_func, callback = request_queue.get()

        try:
            result = request_func()
            if callback:
                callback(result, None)
        except Exception as error:
            if callback:
                callback(None, error)
        finally:
            request_queue.task_done()
            time.sleep(request_interval)


def make_chat_request(prompt):
    def request_func():
        return client.chat.completions.create(
            model="gpt-5.5",
            messages=[{"role": "user", "content": prompt}],
        )

    def callback(result, error):
        if error:
            print(f"Error: {error}")
        else:
            print(f"Response: {result.choices[0].message.content}")

    request_queue.put((request_func, callback))


def make_responses_request(prompt):
    """Responses API equivalent for the same queue."""
    request_queue.put(
        (
            lambda: client.responses.create(model="gpt-5.5", input=prompt),
            lambda result, error: print(error or result.output_text),
        )
    )


queue_thread = threading.Thread(target=process_queue, daemon=True)
queue_thread.start()

for i in range(10):
    make_chat_request(f"Request {i}: Tell me a fact about space")

Rate Limit Strategies for Different Scenarios

Interactive Applications

For applications with user interaction:

  1. Implement client-side throttling to prevent users from making too many requests
  2. Show loading indicators to provide feedback during API calls
  3. Cache responses for common queries to reduce API calls

Batch Processing

Warning

Feature Not Implemented!

This functionality is currently under development and not yet available in AvalAI. We’ll announce its release through our official channels. Stay tuned for updates!

For batch processing applications:

  1. Schedule jobs during off-peak hours to avoid rate limit issues
  2. Process in smaller batches to distribute requests over time
  3. Implement retry logic with increasing delays between batches

High-Availability Systems

For systems requiring high availability:

  1. Implement multiple API keys with load balancing
  2. Set up fallback mechanisms for when rate limits are reached
  3. Maintain a token/request budget to ensure critical operations have priority

Upgrading Your Rate Limits

If you consistently hit rate limits, here are the fastest ways to get more headroom:

  1. Verify your phone number to jump from the Basic tier to Tier 1 — instantly, with no top-up required.
  2. Top up your account to climb to Tier 2 and beyond. Tiers are based on cumulative top-ups, so every contribution counts toward your next upgrade.
  3. Optimize your implementation to reduce unnecessary API calls (batching, caching, and choosing the right model size all help).
  4. Check your current tier and progress at any time on your account dashboard.

Upgrades are automatic and instant the moment you cross the next threshold — no support tickets, no waiting, and all of your credit stays available for API usage after each upgrade.

Conclusion

Effective rate limit management is essential for building reliable applications with the AvalAI API. By implementing the strategies outlined in this guide, you can minimize disruptions due to rate limiting and ensure a smooth experience for your users.

Remember that rate limits may change over time as the API evolves. Always refer to the most up-to-date documentation for the latest information on rate limits.