Skip to content

Rate Limits

Every request to the StudyPlug API includes rate limit information in the response headers. When you exceed the limit, the API returns a 429 Too Many Requests response with details on when to retry.

TierPer MinutePer DayKeyed By
Anonymous (no API key)30200IP address
Free (API key)30500API key
Pro (API key)12010,000API key

To get an API key, submit a request. See Authentication for details.

Every successful response includes these headers:

HeaderDescriptionExample
X-RateLimit-LimitMaximum requests allowed in the window30
X-RateLimit-RemainingRequests remaining in the current window14
X-RateLimit-ResetUnix timestamp (seconds) when the window resets1708700000

When rate-limited, the response also includes:

HeaderDescriptionExample
Retry-AfterSeconds to wait before retrying8

Rate-limited responses use the RFC 7807 Problem Details format:

{
"type": "https://api.studyplug.org/errors/rate-limited",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "You have exceeded 30 requests per minute. Please wait before retrying.",
"instance": "/api/v1/generate",
"retryAfter": 8
}

The retryAfter field in the body matches the Retry-After header value and indicates the number of seconds to wait.

The TypeScript SDK automatically retries on 429 responses with exponential backoff. It reads the Retry-After header (or the retryAfter body field) to determine how long to wait.

import { StudyPlug, isRateLimitError } from "studyplug";
const sp = new StudyPlug({
maxRetries: 2, // default: 2 retries on 429
});
try {
const { data } = await sp.generate({ skill: "add-within-10", count: 5 });
} catch (err) {
if (isRateLimitError(err)) {
// All retries exhausted -- err.retryAfter has the wait time in seconds
console.log(`Rate limited. Retry after ${err.retryAfter}s`);
}
}

Set maxRetries: 0 to disable automatic retries and handle 429 responses yourself.

Use seeds to leverage caching. Seeded requests with the same parameters return cached results instantly and are much faster than fresh generation. If you need the same content more than once, always pass a seed.

Terminal window
# This response is cached server-side after the first call
curl -X POST https://api.studyplug.org/api/v1/generate \
-H "Content-Type: application/json" \
-d '{"skill": "add-within-10", "count": 10, "seed": 42}'

Cache responses on your side. Store generated content in your own database or cache layer. Content items are static data — they do not change once generated with a given seed.

Batch instead of looping. Use the count parameter (up to 50) to get multiple items in a single request rather than making one request per item.

// Good: one request for 20 items
const { data } = await sp.generate({ skill: "add-within-10", count: 20 });
// Avoid: 20 separate requests
for (let i = 0; i < 20; i++) {
await sp.generate.single({ skill: "add-within-10" }); // wastes rate limit
}

Monitor the headers. Check X-RateLimit-Remaining in your responses to proactively slow down before hitting the limit, rather than relying on retries after a 429.