Skip to main content

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

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 window10 minutesReal time (per second)
What is limitedCall count, processing timeCall speed
PreventsSteady overuse throughout the dayBursts within a short window
How to check429 response on excessX-Api-Call-Limit response header
tip

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.

ItemDefaultDescription
Call count3,000 per 10 minutesTotal API requests allowed within 10 minutes
Processing time600 seconds per 10 minutesCumulative 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.

info

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

ItemValueMeaning
Bucket capacity40Maximum requests that can accumulate at once
Drain rate2 per second2 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)
tip

Watching this header and throttling proactively is more reliable than reacting after a 429 has occurred.


🔀 Differences by API

APITotal QuotaBurst RateNotes
Admin API3,000 calls / 600s per 10 minBucket 40, drains 2/secMeasured per Access Token
Front API (Basic auth)Default quotaBucket 40, drains 2/secTreated as an authenticated request
Front API (unauthenticated)Reduced limitReduced limitBasic authentication recommended
D.Collection APIMax 40 per minute per IPSeparate 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')
SituationRecommendation
Collecting full listsMaximize limit to reduce call count, and pause between pages
Bulk create/updateCall sequentially rather than in parallel, with at least 0.5s between requests
Batch jobsSpread execution outside business hours
Real-time syncNarrow the range with date parameters to fetch only changes
warning

Retrying failed requests immediately, without backoff, keeps the bucket full and blocks legitimate requests as well. Always wait before retrying.