Rate limits and daily quotas
Ur Next Door API daily quotas per plan and action, the 60 requests a minute limit, rate limit headers, UTC midnight resets, and size limits.
Two limits apply to API use: a daily quota for each kind of create, and a burst limit on requests a minute. Both are per member: all of your keys share them, so five keys do not give you five times the quota.
Daily quotas
Each successful create or upload uses one unit of its action's quota for the current UTC day:
| Action | Free | Pro | Business |
|---|---|---|---|
post | 20 | 60 | 200 |
question | 20 | 60 | 200 |
poll | 10 | 30 | 100 |
mcq | 30 | 90 | 300 |
community | 2 | 5 | 20 |
service | 5 | 15 | 50 |
job | 5 | 15 | 50 |
media | 50 | 150 | 500 |
- The columns are plans. Your plan is shown by
GET /api/v1/meandGET /api/v1/usage; you can change it in Settings > Billing. communityis small on purpose: communities are long lived.- Quotas count only API requests. What you do on the website or in the app never uses them.
- A scheduled create counts on the day you schedule it, not the day it goes live. Cancelling it later does not give the unit back.
- Reads and schedule management are not counted:
GET /me,GET /usage, the lookups,GET /scheduled, reschedule, publish now and cancel.
Failed requests never count
Only a successful answer (2xx) uses quota. A 422 because of a typo, a 403, a 409 or even a 500 gives the unit back at once. Fix the problem and try again.
When the day resets
Counters reset at 00:00 UTC every day (05:30 in India). X-RateLimit-Reset and resets_at give the exact moment.
Check your usage
curl "https://urnextdoor.com/api/v1/usage" \
-H "Authorization: Bearer $UND_API_KEY"const res = await fetch("https://urnextdoor.com/api/v1/usage", {
headers: {
Authorization: `Bearer ${process.env.UND_API_KEY}`,
},
});
console.log(res.status, await res.json());import os
import requests
api_key = os.environ["UND_API_KEY"]
response = requests.get(
"https://urnextdoor.com/api/v1/usage",
headers={
"Authorization": f"Bearer {api_key}",
},
timeout=30,
)
print(response.status_code, response.json())<?php
$apiKey = getenv('UND_API_KEY');
$ch = curl_init('https://urnextdoor.com/api/v1/usage');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
echo $status, PHP_EOL, $body, PHP_EOL;Sample response: 200 OK
{
"ok": true,
"plan": "free",
"day": "2026-10-15",
"resets_at": "2026-10-16T00:00:00Z",
"quotas": [
{
"action": "post",
"limit": 20,
"used": 3,
"remaining": 17
},
{
"action": "question",
"limit": 20,
"used": 0,
"remaining": 20
},
{
"action": "media",
"limit": 50,
"used": 2,
"remaining": 48
}
],
"request_id": "9f8e7d6c5b4a3921"
}Every quota-counted response also carries three headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Today's limit for this action |
X-RateLimit-Remaining | Units left today for this action |
X-RateLimit-Reset | Unix seconds of the next UTC midnight |
When the quota runs out
The request answers 429 with the code quota_exceeded and a Retry-After header (seconds until the reset):
{
"ok": false,
"error": "You have used today's 20 posts for the API. The limit resets at 00:00 UTC.",
"code": "quota_exceeded",
"request_id": "a1b2c3d4e5f60718"
}Do not retry before the reset; schedule the rest for tomorrow instead, or upgrade your plan.
The burst limit: 60 requests a minute
Across every endpoint, counted or not, a member may make 60 requests a minute. Beyond that, requests answer 429 with the code rate_limited and a Retry-After header. Wait that many seconds and continue.
Separately, repeated failed key checks from one network address are limited, so a script stuck in a loop with a wrong key is slowed down. Fix the key first.
A simple, polite client:
async function call(url, options, attempts = 3) {
for (let i = 0; i < attempts; i++) {
const res = await fetch(url, options);
if (res.status !== 429 && res.status < 500) return res;
const body = await res.clone().json().catch(() => ({}));
if (body.code === "quota_exceeded") return res;
const wait = Number(res.headers.get("Retry-After") || 2 ** i);
await new Promise((r) => setTimeout(r, wait * 1000));
}
return fetch(url, options);
}Reuse the same Idempotency-Key in options across the attempts, so a retried create never posts twice.
Size limits
| Limit | Value |
|---|---|
| JSON request body | 256 KB |
JSON request body for POST /media | 12 MB |
| Image in | 8 MB, PNG, JPEG, GIF or WebP |
| Image stored | 2 MB or less after conversion to WebP |
gallery | 12 images |
Poll and MCQ options | 2 to 5 |
Service packages | 3 |
Service faqs | 20 |
| Active API keys per member | 5 |
scheduled_at | 5 minutes to 180 days ahead |
Over a size limit, the request answers 413 payload_too_large.
Frequently asked questions
Do all my keys share one quota?
Yes. Quotas and the burst limit are per member, across all of your keys.
Does posting on the website use my API quota?
No. Only requests made with an API key count.
Does a failed request use quota?
No. Anything that is not a 2xx answer gives the unit back immediately.
How do I get higher limits?
Higher plans have higher quotas, as the table shows. Upgrade in Settings > Billing on the website.
Next steps
- Errors.
- Idempotency for safe retries.
- Schedule content.
Last updated