The values below are those in effect on November 5, 2026. The portal’s “Limits” tab shows the ones that apply to your workspace and lets you set spend caps (open).
Rate limitsLink to the Rate limits section
| Limit | Value | Response beyond it |
|---|---|---|
| Requests per key | 600 per minute | 429 with Retry-After |
| Refused requests with the same key (revoked key, address not allowed…) | 60 per minute | 429 |
| Authentication failures from the same address | 60 per minute | 429 |
- The rate limit counts per key, not per workspace: several keys each have their own.
- A valid key that has just been used is not slowed down because someone else at the same address (corporate network, NAT) is using the wrong key.
- An IPv6 address is counted together with its whole /64 prefix.
- The portal’s “Limits” tab shows the per-key limit, under “Rate limits”.
Concurrent requestsLink to the Concurrent requests section
Chat has no limit on the number of concurrent requests: each request holds its share of the balance (see Hold), and it is the balance that limits what can run at the same time. When the holds in progress block a new request that would otherwise fit, the API responds with 429 (Retry-After: ).
Media endpoints have a number of requests in flight per workspace:
| Endpoint | Requests in flight |
|---|---|
| Images | 8 |
| Videos (unfinished jobs) | 20 |
| Video downloads | 4 |
| Speech | 8 |
| Transcription | 4 |
| Embeddings | 8 |
| OCR | 2 |
Beyond that: 429 with Retry-After (30 seconds for videos, 5 seconds otherwise).
SizesLink to the Sizes section
| Endpoint | Limit |
|---|---|
/ | The model’s context window (context_length in /v1/models). With Moon Blur, each text is 500,000 characters at most. |
/ | 1 MB JSON body. |
/ | 90 MB body; images of 20 MB and 40 megapixels each. |
/v1/videos | 60 MB body; 20 MB images. |
/ | 256 KB body; 4,096 characters of text. |
/ | 25 MB file and 20 minutes of audio. |
/ | 8 MB body; 2,048 texts and about 1 million tokens. |
/v1/ocr | 30 MB document; 50 pages per request. |
A multipart upload must include a Content-Length header (otherwise 411 ).
TimeoutsLink to the Timeouts section
| Case | Duration |
|---|---|
Streamed chat (stream: true) | Up to one hour. The stream is cut if the model sends nothing for 5 minutes. |
| Non-streamed chat | The response must arrive within about 100 seconds: beyond that, the network may cut the connection. |
| Images, speech, transcription, embeddings | We wait 85 seconds at most for the model. |
| OCR | About 85 seconds; pages not read in time are neither returned nor billed. |
| Videos | Starting a video responds right away; you then track the video (see Videos). |
Spend capsLink to the Spend caps section
Two levels of caps limit what the API can spend. They are set in euros.
| Level | Where | Windows |
|---|---|---|
| Workspace | “Limits” tab, “Workspace spend caps” section: “Per hour (€)”, “Per day (€)”, “Per month (€)”, then “Save limits”. | Sliding: the last hour, the last 24 hours and the last 30 days. Leave empty for no limit. |
| Key | When the key is created: “Spend cap (€)” and “Period”. See Authentication. | A sliding window of one hour, 24 hours or 30 days. |
- Each request must fit within every cap that applies to it, hold included. Beyond that:
402(withspend_cap_exceeded scopeandwindow), or402when the hold of this single request exceeds what the cap leaves.hold_exceeds_cap - The owner and the billing contact get an email when a cap is reached.
- A sliding window frees up over time: spend from 61 minutes ago no longer counts toward the hourly cap.
Retry without paying twiceLink to the Retry without paying twice section
Each HTTP request received has its own ID (X-Moon-Request-Id) and is billed only once. But the API does not recognize a retry on your side: sending the same request again creates a second one, with its own hold and its own cost. There is no idempotency header.
| Case | Retry? |
|---|---|
429 with Retry-After | Yes, after the delay. The refused request costs nothing. |
402, 400, 401, 403, 404, 413 | No: fix the cause first. Nothing is charged. |
503 (moon_blur_unavailable, billing_unavailable, service_unavailable, pricing_unavailable) | Yes, after Retry-After or a few seconds. Nothing is charged. |
502 | Yes. Nothing is charged if the model produced nothing. |
504 on chat, dropped connection, your client’s timeout reached | With care: the first request may have been charged (its hold is kept). Check spend in “Usage” › “Request log”, or with GET / if you received the request ID, before resending an expensive request. On media, a 504 costs nothing. |
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.realmoon.ai/v1",
api_key=os.environ["MOONAI_API_KEY"],
max_retries=0,
timeout=600,
)import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.realmoon.ai/v1',
apiKey: process.env.MOONAI_API_KEY,
maxRetries: 0,
timeout: 600_000,
});