Skip to content

Rate Limits

The Suwappu Agent API enforces rate limits using a sliding window mechanism. Limits vary by tier and are applied per API key.

Tiers

TierRequests per MinuteDescription
Free30Default tier for newly registered agents
Agent100For active trading agents
Pro500For high-frequency and production workloads

All limits use a 1-minute sliding window. The window tracks requests over the last 60 seconds, not fixed calendar minutes.

Response Headers

Every API response includes rate limit headers so you can track your usage in real time:

HeaderDescriptionExample
X-RateLimit-LimitMaximum requests allowed per minute for your tier30
X-RateLimit-RemainingRequests remaining in the current window27
X-RateLimit-ResetUnix timestamp (seconds) when the window resets1705312260
Example response headers:
HTTP/1.1 200 OK

Content-Type: application/json

X-RateLimit-Limit: 30

X-RateLimit-Remaining: 27

X-RateLimit-Reset: 1705312260

Handling 429 Too Many Requests

When you exceed your rate limit, the API returns a 429 status with a Retry-After header indicating how many seconds to wait before retrying.

Response:
HTTP/1.1 429 Too Many Requests

Content-Type: application/json

Retry-After: 12

X-RateLimit-Limit: 30

X-RateLimit-Remaining: 0

X-RateLimit-Reset: 1705312260

{

"hl-key">"success": false,

"hl-key">"error": {

"hl-key">"code": "RATE_LIMITED",

"hl-key">"message": "Rate limit exceeded. Retry after 12 seconds."

}

}

Public Endpoints

Public endpoints (POST /register, GET /chains, GET /openapi) are not subject to per-key rate limiting.

Code Examples

Python

import time
import requests

BASE_URL = class="hl-str">"https:class="hl-commentclass="hl-str">">//api.suwappu.bot/v1/agent"

API_KEY = class="hl-str">"suwappu_sk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

headers = {

class="hl-str">"Content-Type": class="hl-str">"application/json",

class="hl-str">"Authorization": fclass="hl-str">"Bearer {API_KEY}",

}

def request_with_retry(method: str, url: str, max_retries: int = 3, **kwargs):

class="hl-str">""class="hl-str">"Make an API request with automatic retry on rate limit."class="hl-str">""

for attempt in range(max_retries):

response = requests.request(method, url, headers=headers, **kwargs)

class=class="hl-str">"hl-comment"># Log rate limit status

remaining = response.headers.get(class="hl-str">"X-RateLimit-Remaining")

limit = response.headers.get(class="hl-str">"X-RateLimit-Limit")

if remaining is not None:

print(fclass="hl-str">"Rate limit: {remaining}/{limit} requests remaining")

class=class="hl-str">"hl-comment"># If not rate limited, return the response

if response.status_code != 429:

response.raise_for_status()

return response.json()

class=class="hl-str">"hl-comment"># Rate limited — wait and retry

retry_after = int(response.headers.get(class="hl-str">"Retry-After", 5))

print(fclass="hl-str">"Rate limited. Retrying in {retry_after}s (attempt {attempt + 1}/{max_retries})")

time.sleep(retry_after)

raise Exception(class="hl-str">"Max retries exceeded due to rate limiting")

class=class="hl-str">"hl-comment"># Usage

quote = request_with_retry(

class="hl-str">"POST",

fclass="hl-str">"{BASE_URL}/quote",

json={

class="hl-str">"from_token": class="hl-str">"USDC",

class="hl-str">"to_token": class="hl-str">"ETH",

class="hl-str">"amount": class="hl-str">"500.00",

class="hl-str">"chain": class="hl-str">"ethereum",

},

)

print(quote)

TypeScript

const BASE_URL = class="hl-str">"https:class="hl-commentclass="hl-str">">//api.suwappu.bot/v1/agent";
const API_KEY = class="hl-str">"suwappu_sk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6";

const headers = {

class="hl-str">"Content-Type": class="hl-str">"application/json",

Authorization: Bearer ${API_KEY},

};

async function requestWithRetry(

method: string,

url: string,

body?: object,

maxRetries = 3

): Promise<any> {

for (let attempt = 0; attempt < maxRetries; attempt++) {

const response = await fetch(url, {

method,

headers,

body: body ? JSON.stringify(body) : undefined,

});

class=class="hl-str">"hl-comment">// Log rate limit status

const remaining = response.headers.get(class="hl-str">"X-RateLimit-Remaining");

const limit = response.headers.get(class="hl-str">"X-RateLimit-Limit");

if (remaining !== null) {

console.log(Rate limit: ${remaining}/${limit} requests remaining);

}

class=class="hl-str">"hl-comment">// If not rate limited, return the response

if (response.status !== 429) {

if (!response.ok) {

throw new Error(Request failed: ${response.status});

}

return response.json();

}

class=class="hl-str">"hl-comment">// Rate limited — wait and retry

const retryAfter = parseInt(response.headers.get(class="hl-str">"Retry-After") ?? class="hl-str">"5", 10);

console.log(

Rate limited. Retrying in ${retryAfter}s (attempt ${attempt + 1}/${maxRetries})

);

await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));

}

throw new Error(class="hl-str">"Max retries exceeded due to rate limiting");

}

class=class="hl-str">"hl-comment">// Usage const quote = await requestWithRetry(class="hl-str">"POST", ${BASE_URL}/quote, {

from_token: class="hl-str">"USDC",

to_token: class="hl-str">"ETH",

amount: class="hl-str">"500.00",

chain: class="hl-str">"ethereum",

});

console.log(quote);

Best Practices

  • Monitor headers proactively. Check X-RateLimit-Remaining on every response and throttle before hitting zero.
  • Always respect Retry-After. Do not retry immediately — the server tells you exactly how long to wait.
  • Use exponential backoff as a fallback. If Retry-After is absent for any reason, back off exponentially (e.g., 1s, 2s, 4s).
  • Batch where possible. Reduce request count by batching operations rather than making many individual calls.
  • Upgrade your tier if you consistently hit rate limits in production.