Rate Limits
Per-plan rate limits for the Markdown Anything API.
Rate limits protect the API from abuse and ensure fair usage across all workspaces. Limits are applied per workspace, not per token.
Conversion Rate Limits
The POST /convert endpoint is rate-limited based on your workspace's plan:
| Plan | Conversions per Minute |
|---|---|
| Free | 20 |
| Starter | 60 |
| Professional | 120 |
| Business | 240 |
General API Rate Limit
All other authenticated API endpoints (including GET /conversions/{id}) share a general rate limit of 120 requests per minute per workspace.
Rate Limit Headers
When you approach or exceed the rate limit, the API includes standard rate limit headers in the response:
Prop
Type
429 Too Many Requests
When you exceed the rate limit, the API returns a 429 status code:
{
"message": "Too Many Attempts."
}Handling 429 Responses
async function convertWithRetry(form, token, maxRetries = 3) {
for (let i = 0; i <= maxRetries; i++) {
const response = await fetch(
"https://markdownanything.com/api/v1/convert",
{
method: "POST",
headers: { Authorization: `Bearer ${token}` },
body: form,
}
);
if (response.status !== 429) {
return response.json();
}
const retryAfter = response.headers.get("Retry-After") || 60;
console.log(`Rate limited. Retrying in ${retryAfter}s...`);
await new Promise((r) => setTimeout(r, retryAfter * 1000));
}
throw new Error("Rate limit exceeded after max retries");
}import time
import requests
def convert_with_retry(file_path, token, max_retries=3):
url = "https://markdownanything.com/api/v1/convert"
headers = {"Authorization": f"Bearer {token}"}
for i in range(max_retries + 1):
with open(file_path, "rb") as f:
response = requests.post(
url, headers=headers, files={"file": f}
)
if response.status_code != 429:
return response.json()
retry_after = int(response.headers.get("Retry-After", 60))
print(f"Rate limited. Retrying in {retry_after}s...")
time.sleep(retry_after)
raise Exception("Rate limit exceeded after max retries")Best Practices
- Respect
Retry-After. Always check theRetry-Afterheader before retrying — it tells you exactly how long to wait. - Use exponential backoff. If
Retry-Afteris not present, back off exponentially (e.g. 1s, 2s, 4s, 8s). - Use async mode for batch jobs. Instead of sending many sync requests, use async mode with webhooks to queue conversions and receive results as they complete.
- Upgrade your plan. If you consistently hit rate limits, consider upgrading to a higher plan for increased throughput.
Rate limits are tracked per workspace, not per API token. Multiple tokens on the same workspace share the same rate limit budget.