API Quota Guide
CAFE24 APIs limit call volume to keep the service stable.
Limits operate in two layers — total volume control and burst rate control — and exceeding either one returns a 429 Too Many Requests response.
📚 Table of Contents
- Two-Layer Quota Structure
- Default Quota
- Burst Rate Limit
- X-Api-Call-Limit Header
- Differences by API
- Handling 429
🧭 Two-Layer Quota Structure
The two limits guard against different problems. Total volume caps how much you can use over a period, while burst rate controls momentary spikes.
① Total Volume (Quota) ② Burst Rate (Leaky Bucket)
┌──────────────────────────┐ ┌──────────────────────────┐
│ Measured per 10 minutes │ │ Bucket capacity 40 │
│ · 3,000 calls │ │ Drains 2 per second │
│ · 600 seconds │ │ │
│ │ │ Blocks sudden spikes │
│ Controls sustained use │ │ │
└──────────────────────────┘ └──────────────────────────┘
│ │
└──────────────┬───────────────────────┘
▼
429 Too Many Requests on excess
| Category | ① Total Volume | ② Burst Rate |
|---|---|---|
| Measurement window | 10 minutes | Real time (per second) |
| What is limited | Call count, processing time | Call speed |
| Prevents | Steady overuse throughout the day | Bursts within a short window |
| How to check | 429 response on excess | X-Api-Call-Limit response header |
The two limits are independent. You can stay well under the per-second rate and still hit 429 by exhausting the 10-minute total; conversely, plenty of remaining quota will not save a request burst.
📊 Default Quota
Unless configured otherwise, the following defaults apply.
| Item | Default | Description |
|---|---|---|
| Call count | 3,000 per 10 minutes | Total API requests allowed within 10 minutes |
| Processing time | 600 seconds per 10 minutes | Cumulative time available for API processing within 10 minutes |
About processing time
If you repeatedly call slow endpoints, processing time can run out before the call count does.
e.g. Calling an API averaging 1s response 600 times in 10 minutes
Call count : 600 / 3,000 → plenty left
Processing time : 600 / 600s → exhausted ⚠️ further requests get 429
For bulk retrieval, increasing the page size via the limit parameter — thereby reducing the number of calls — consumes less quota than repeatedly calling a heavy endpoint.
See the GET API Usage Guide for query parameter details.
If a specific quota has been configured for a shopping mall, that setting applies instead of the defaults above.
🪣 Burst Rate Limit
Independently of the total quota, sudden request spikes are controlled by a Leaky Bucket algorithm.
How it works
1 request = 1 drop
│
▼
┌─────────┐
│ ▓▓▓▓▓▓▓ │ Bucket capacity: 40
│ ▓▓▓▓▓▓▓ │ → 429 when full
└────┬────┘
│ Drains 2 per second
▼
| Item | Value | Meaning |
|---|---|---|
| Bucket capacity | 40 | Maximum requests that can accumulate at once |
| Drain rate | 2 per second | 2 requests leave the bucket every second |
Practical guidance
- Calling 2 times per second or less never fills the bucket, so no restriction applies.
- Brief spikes above that rate are tolerated up to the bucket capacity (40).
- Sustained rates above 2 per second fill the bucket and trigger 429.
📮 X-Api-Call-Limit Header
Every API response includes the current bucket state as a header.
X-Api-Call-Limit: 1/40
│ │
│ └─ Bucket capacity
└──── Current usage
Example
curl -i -X GET \
'https://yourmall.cafe24api.com/api/v2/admin/products' \
-H 'Authorization: Bearer {access_token}'
# Response headers
# HTTP/1.1 200 OK
# X-Api-Call-Limit: 1/40
Node.js
const response = await axios.get(url, { headers });
const callLimit = response.headers['x-api-call-limit']; // "1/40"
const [used, capacity] = callLimit.split('/').map(Number);
// Slow down once the bucket is over 80% full
if (used / capacity > 0.8) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
Python
response = requests.get(url, headers=headers)
call_limit = response.headers.get('X-Api-Call-Limit') # "1/40"
used, capacity = map(int, call_limit.split('/'))
# Slow down once the bucket is over 80% full
if used / capacity > 0.8:
time.sleep(1)
Watching this header and throttling proactively is more reliable than reacting after a 429 has occurred.
🔀 Differences by API
| API | Total Quota | Burst Rate | Notes |
|---|---|---|---|
| Admin API | 3,000 calls / 600s per 10 min | Bucket 40, drains 2/sec | Measured per Access Token |
| Front API (Basic auth) | Default quota | Bucket 40, drains 2/sec | Treated as an authenticated request |
| Front API (unauthenticated) | Reduced limit | Reduced limit | Basic authentication recommended |
| D.Collection API | — | Max 40 per minute per IP | Separate policy |
Front API call limits differ depending on whether the request is authenticated.
Passing only client_id is treated as unauthenticated and receives a lower limit, so use Basic authentication in production.
See the OAuth 2.0 Authentication Guide for authentication details.
🐛 Handling 429
Response
HTTP/1.1 429 Too Many Requests
X-Api-Call-Limit: 40/40
Exponential backoff
When you receive a 429, do not retry immediately — increase the wait time between retries.
Node.js
async function requestWithRetry(config, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await axios(config);
} catch (error) {
if (error.response?.status !== 429) {
throw error;
}
// 1s → 2s → 4s → 8s → 16s
const waitMs = Math.pow(2, attempt) * 1000;
console.warn(`429 received, retrying in ${waitMs}ms (${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, waitMs));
}
}
throw new Error('Exceeded maximum retries');
}
Python
import time
def request_with_retry(method, url, headers, max_retries=5, **kwargs):
for attempt in range(max_retries):
response = requests.request(method, url, headers=headers, **kwargs)
if response.status_code != 429:
return response
# 1s → 2s → 4s → 8s → 16s
wait_sec = 2 ** attempt
print(f'429 received, retrying in {wait_sec}s ({attempt + 1}/{max_retries})')
time.sleep(wait_sec)
raise Exception('Exceeded maximum retries')
Recommended patterns for bulk work
| Situation | Recommendation |
|---|---|
| Collecting full lists | Maximize limit to reduce call count, and pause between pages |
| Bulk create/update | Call sequentially rather than in parallel, with at least 0.5s between requests |
| Batch jobs | Spread execution outside business hours |
| Real-time sync | Narrow the range with date parameters to fetch only changes |
Retrying failed requests immediately, without backoff, keeps the bucket full and blocks legitimate requests as well. Always wait before retrying.
📚 Related Documents
- API Status Code Guide — All status codes including 429
- OAuth 2.0 Authentication Guide — Admin/Front API authentication
- GET API Usage Guide — Reducing call count with query parameters