API Reference

Rate Limits

Rate limiting and quotas

Solvela applies rate limiting at multiple layers to protect gateway stability and ensure fair usage across all clients.

Middleware Stack

Requests pass through the following limiting layers in order:

LayerScopeDescription
Per-IP rate limitingClient IP addressPrevents abuse from a single origin before wallet identity is established
Per-wallet rate limitingSolana wallet addressPrimary limit for x402 users; each wallet has an independent request budget
Per-key rate limitingAPI keyApplied for enterprise users instead of per-wallet limits
Global concurrency limitingGateway-wideCaps total in-flight requests across all clients to prevent overload
Request timeoutPer requestHard timeout applied globally; long-running requests are terminated

Rate Limit Headers

Every response includes headers indicating the current limit state for your wallet or key:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the current window resets

When a request is rejected due to rate limiting, the gateway returns 429 Too Many Requests with a rate_limited error type. Use the X-RateLimit-Reset value to determine when to retry.

# Example response headers
HTTP/2 200
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1712345678

Note

Rate limit windows and exact thresholds are subject to change. Always read the headers from live responses rather than hardcoding expected values.

Enterprise Configuration

Enterprise organizations using API keys can configure rate limits and spending controls through the dashboard:

Tip

Use session budgets in SDKs when building user-facing products. Pass a session token to each user rather than your root API key. This prevents any single user from exhausting your organization's budget and isolates spend by user in the audit log.

Handling Rate Limit Errors

When you receive a 429 response, back off until the reset window expires:

async function chatWithBackoff(client: SolvelaClient, params: ChatParams) {
  const res = await client.chatRaw(params);

  if (res.status === 429) {
    const resetAt = parseInt(res.headers.get("X-RateLimit-Reset") ?? "0", 10);
    const waitMs = Math.max(0, resetAt * 1000 - Date.now());
    await new Promise((resolve) => setTimeout(resolve, waitMs));
    return client.chatRaw(params); // retry once after window resets
  }

  return res;
}

Warning

Do not retry on 429 immediately in a tight loop. This will not succeed and will count against your limit once the window resets. Always wait for X-RateLimit-Reset before retrying.