Skip to main content

Overview

The Junis External API implements rate limiting to ensure fair usage and maintain service quality for all users. Rate limits are applied per API key, and all keys of an organization also share one organization-wide total per minute and per hour. You can set each key’s limits yourself, up to 1,000 requests per minute and 100,000 per hour. Base URL: https://api.junis.ai
Each API key has its own per-minute and per-hour counters. On top of that, all keys of an organization share one total (300 requests per minute by default), so creating more keys does not raise the organization’s total.

Rate Limiting Architecture

The External API uses Redis-based fixed-window counters with up to four windows (per key per minute, per key per hour, per organization per minute, and per organization per hour when set) for distributed rate limiting across multiple server instances.
Storage: Redis with distributed support across all API serversWindows: Four fixed windows aligned to the clock
  • Per key, per minute: resets at the start of every minute
  • Per key, per hour: resets at the start of every hour
  • Per organization, per minute: all keys of the organization combined, resets at the start of every minute
  • Per organization, per hour: all keys combined, resets at the start of every hour. Only applies when your organization has an hourly total set; only requests that passed every per-minute check count toward it
Algorithm: Fixed-window counters with atomic increments (one Redis round trip per request)
Check Before Request: Rate limits are checked before processing your requestHeaders Included: Every response includes current rate limit status429 on Exceed: Returns 429 Too Many Requests if limit exceededAutomatic Reset: Counters automatically reset at the end of each window

Default Rate Limits

When you create a new API key, the following default limits apply:

Changing the limits

The per-hour value must be at least the per-minute value. Leave a field blank to keep the default. Changes apply from the next request, with no redeploy.
The same per-key change is available from code through the admin API: PUT /api/admin/api-keys/{key_id} (organization keys) or PUT /api/user/api-keys/{key_id}/rate-limits (personal keys) with rate_limit_per_minute and/or rate_limit_per_hour. Raising a key above the organization total does not help: every request also counts toward the organization total.

Rate Limit Headers

Every API response includes headers that show your current rate limit status.

Response Headers

Responses also carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Window without a suffix. Those belong to a platform-level flood guard in front of the key limiter and are not your key’s quota — read the suffixed headers above.
Always monitor X-RateLimit-Remaining-* headers to avoid hitting rate limits. Consider pausing requests when remaining count is low.

429 Too Many Requests

When you exceed your rate limit, the API returns a 429 status code.

Response Format

HTTP Status:
Headers:
Body:
When the organization-wide total is exceeded, window is org_minute, limit is the organization total and message reads Organization rate limit exceeded: 300 requests per minute across all API keys. The organization per-hour total works the same way with window set to org_hour. The windows are checked in this order: key per minute, key per hour, organization per minute, organization per hour.

Handling Rate Limits

Best Practices

  • Monitor Headers: Always check X-RateLimit-Remaining-Minute, X-RateLimit-Remaining-Hour, X-RateLimit-Remaining-Org-Minute (and X-RateLimit-Remaining-Org-Hour if present) headers to track your usage
  • Implement Exponential Backoff: When you receive a 429 response, use the Retry-After header value to wait before retrying
  • Cache Responses: Implement caching (TTL: 5 minutes recommended) to reduce API calls for frequently accessed data
  • Batch Requests: Use paginated endpoints instead of individual requests (e.g., GET /api/external/sessions?limit=100)
  • Use Streaming: For real-time chat, use stream: true parameter instead of polling to avoid repeated API calls

Rate Limit Optimization

Identify Bottlenecks

  1. Log Rate Limit Headers: Track X-RateLimit-Remaining-* headers in your application logs
  2. Analyze Request Patterns: Identify high-frequency endpoints that may benefit from caching or batching
    • Repeated session fetches → Add caching
    • Individual message fetches → Use paginated list endpoints
    • Polling for updates → Switch to streaming
  3. Implement Caching: Use Redis or in-memory cache with 5-minute TTL for frequently accessed data
  4. Monitor & Alert: Set up alerts when rate limit usage exceeds 90%

Testing Rate Limits

Local Testing

Test your rate limit handling before deploying to production:

Increasing Rate Limits

Per-key limits are stored on the key itself, so they can be changed without redeploying anything:
  1. An organization admin calls PUT /api/admin/api-keys/{key_id} (JWT authentication) with rate_limit_per_minute (1–1,000) and/or rate_limit_per_hour (1–100,000).
  2. The new values apply from the next request made with that key.
Only organization admins can modify API key rate limits. Raising a key above the organization-wide total (300 requests per minute across all keys by default) does not add capacity on its own — the organization total still applies. Contact Junis to raise the organization total.
Set rate limits based on your actual usage patterns. Start conservative and increase as needed.

FAQs

Answer: Both. Each key has its own per-minute and per-hour limits, and all keys of the organization share one per-minute total (300 by default).Example: If your organization has 2 API keys:
  • API Key 1: 100 requests/minute
  • API Key 2: 100 requests/minute
  • Organization total: 300 requests/minute — the keys together can never exceed it, so adding a third key does not add capacity beyond the total
Response: 429 Too Many Requests with Retry-After headerAction: Wait for the number of seconds specified in Retry-After or until the next window resetNo penalties: No account suspension or additional charges
Per key: Yes — an organization admin updates the key through the admin API (PUT /api/admin/api-keys/{key_id}), and the change applies from the next requestOrganization total: Contact Junis
Answer: Streaming responses count as 1 request, regardless of how long the stream lasts.Example:
  • Non-streaming: 1 request = 1 complete response
  • Streaming: 1 request = entire conversation stream
Streaming is more efficient for real-time chat.
Method 1: Check response headers (X-RateLimit-Remaining-*)Method 2: Set up logging in your application (see Best Practices)Method 3: Monitor 429 error rates in your application metrics

Next Steps

Authentication

Learn about API keys and scopes

Error Codes

Handle 429 and other API errors

Chat Completions API

Start building with streaming

Sessions API

Manage chat sessions efficiently