Limits

JoyToken’s current public limits come from API key quota, key policy, and wallet balance precheck. Do not assume fixed QPS, RPM, or TPM quotas.

Current Limits

LimitSourceResult
Daily quotaAPI key budget402 insufficient_quota
Weekly quotaAPI key budget402 insufficient_quota
Wallet balancePersonal or organization wallet402 insufficient_quota
Model blacklistAPI key policy403 policy_rejected
Tier allowlistAPI key policy and request tier403 policy_rejected
IP allowlist/blocklistAPI key policy403 policy_rejected

Tier Fallback

Every request must include model: "auto"; when the current tier lacks balance, JoyToken may try another tier allowed by policy.

Current tierFallback order
premiumstandard -> economy
standardpremium -> economy
economystandard -> premium

Requests always use model: "auto"; when no eligible candidate remains after policy, tier, wallet, and budget filters, the request fails instead of selecting a caller-specified model.

Client Handling

ErrorRetry?Fix
400NoFix request body
401NoAdd API key
402NoTop up or adjust key budget
403NoAdjust policy, IP, tier, or model
502Short backoffCould be routing or upstream temporary failure
503 / 504YesUse exponential backoff

Exponential Backoff

const retryableStatuses = new Set([502, 503, 504]);
export async function withJoyTokenRetry<T>(fn: () => Promise<T>, attempts = 3) {
let lastError: unknown;
for (let attempt = 0; attempt < attempts; attempt += 1) {
try {
return await fn();
} catch (error: any) {
lastError = error;
const status = error?.status ?? error?.response?.status;
if (!retryableStatuses.has(status) || attempt === attempts - 1) throw error;
await new Promise((resolve) => setTimeout(resolve, 300 * 2 ** attempt));
}
}
throw lastError;
}