Rate Limits

To ensure reliability and fairness across all users, Tsara enforces API rate limits on every endpoint.
These limits prevent abuse and maintain system stability while allowing high-volume applications to operate efficiently.


🚀 Overview

Each API key is allowed a certain number of requests per minute (RPM).
If your application exceeds these limits, Tsara will respond with a 429 Too Many Requests error.

Rate limits apply per:

  • API key
  • Endpoint
  • Environment (Sandbox and Production are independent)

📊 Default Rate Limits

Endpoint GroupRequests per MinuteNotes
Read (GET)120 RPMListing wallets, balances, transactions, etc.
Write (POST/PUT)60 RPMCreating transfers, customers, onramps, etc.
Webhook DeliveryUnlimitedEvent-based, not rate-limited.
Authentication / Identity30 RPMBVN/NIN/CAC verifications.

💡 If you require higher limits, contact [email protected] with your business use case.


⚠️ Exceeding Rate Limits

When your app exceeds a limit, Tsara will return an HTTP 429 response:

Example

{
  "success": false,
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please wait before retrying.",
    "hint": "Retry after 30 seconds."
  },
  "request_id": "req_lim001"
}

Headers returned:

HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 30

🧠 Best Practices

  1. Implement Retry Logic
    Use exponential backoff — retry after the time specified in Retry-After.

  2. Monitor Remaining Quota
    Use the headers X-RateLimit-Remaining and X-RateLimit-Reset to adjust request timing dynamically.

  3. Batch Requests
    Group smaller API calls into bulk requests when possible.

  4. Cache Read Responses
    For high-frequency reads (like balances or transaction history), cache results to minimize redundant requests.

  5. Separate Sandbox & Live Keys
    Each environment tracks limits independently — never reuse keys.


🧾 Example Retry Logic (Node.js)

import axios from "axios";

async function makeRequest() {
  try {
    const res = await axios.get("https://sandbox.tsara.ng/v1/wallets", {
      headers: { Authorization: "Bearer YOUR_SECRET_KEY" }
    });
    console.log(res.data);
  } catch (err) {
    if (err.response?.status === 429) {
      const retryAfter = err.response.headers["retry-after"] || 30;
      console.log(`Rate limit hit. Retrying after ${retryAfter}s...`);
      setTimeout(makeRequest, retryAfter * 1000);
    } else {
      console.error("API Error:", err.response?.data || err.message);
    }
  }
}

makeRequest();

🧩 Advanced Options

  • Enterprise customers can request higher rate limits for high-volume or mission-critical workloads.
  • Webhook deliveries are never rate-limited — they queue automatically.
  • Monitoring dashboards are available in Tsara to visualize request usage per API key.

🔗 Related Pages

  • Errors — Learn about 429 and other response codes.
  • Authentication — Use separate keys for sandbox and live environments.
  • SDKs & Libraries — Recommended techniques for managing retries safely.