@@ -459,39 +459,151 @@ var_dump($gk);
459459 </div >
460460</div >
461461
462- <h3 >Rate Limits </h3 >
462+ <h3 >Rate limits </h3 >
463463<a class =" anchor" id =" apiratelimit" ></a >
464+
464465<div class =" panel panel-default" >
465466 <div class =" panel-body" >
466- <p >In order to protect our service from abuse/misbehaving client… We have rate limiting in place.</p >
467- <p >If you hit a rate limit, we wil respond with the usual http code <code >429</code >.</p >
468- <p >A first set of rule limit the request rate per minutes, for any pages.</p >
469- <p >A second set of rule limit the API calls over a period of time. We're using the <a href =" https://en.wikipedia.org/wiki/Leaky_bucket" target =" _blank" >Leaky Bucket Algorithm</a >.</p >
470- <blockquote cite =" https://en.wikipedia.org/wiki/Leaky_bucket" >
471- The leaky bucket analogy. Water can be added intermittently to the bucket, which leaks out at a constant
472- rate until empty, and will also overflow when full.
473- <img src =" https://upload.wikimedia.org/wikipedia/commons/7/77/Leaky_bucket_analogy.svg" class =" img-responsive" width =" 170" height =" 240" >
467+
468+ <div class =" alert alert-info" role =" alert" style =" margin-bottom :16px " >
469+ <b >Quick summary</b >
470+ <ul style =" margin-bottom :0 " >
471+ <li ><b >Two layers:</b > (1) a global <i >burst</i > limit per minute across endpoints; (2) per-endpoint <i >quota</i > over a longer period (leaky bucket).</li >
472+ <li ><b >Who’s counted:</b > anonymous traffic is counted per <b >IP address</b >; authenticated traffic is counted per <b >account</b >.</li >
473+ <li ><b >Exceeding a limit:</b > we return <code >HTTP 429</code > and standard rate-limit headers.</li >
474+ </ul >
475+ </div >
476+
477+ <p >To keep the service reliable and abuse-resistant, we apply rate limiting.</p >
478+ <p >If you hit a limit, we respond with <code >429 Too Many Requests</code >.</p >
479+
480+ <h4 >How it works</h4 >
481+ <ul >
482+ <li ><b >Layer 1 – Burst (RPM):</b > caps short spikes across all endpoints per minute.</li >
483+ <li ><b >Layer 2 – Endpoint quota:</b > each API endpoint also has a longer-period allowance enforced with the
484+ <a href =" https://en.wikipedia.org/wiki/Leaky_bucket" target =" _blank" rel =" noopener" >Leaky Bucket algorithm</a >.
485+ </li >
486+ </ul >
487+
488+ <blockquote cite =" https://en.wikipedia.org/wiki/Leaky_bucket" >
489+ The leaky bucket analogy: water can be added intermittently, leaks at a constant rate, and overflows when full.
490+ <img src =" { GK_CDN_IMAGES_URL} /help/Leaky_bucket_analogy.svg" class =" img-responsive" width =" 170" height =" 240" alt =" Leaky bucket analogy" >
474491 </blockquote >
475- <p >The limits are set per IP or per secid depending if the call is authenticated or not.</p >
492+
493+ <h5 >Check usage</h5 >
476494 <p >
477- Your current API usage is available in the headers of each API call. You can also get your current Rate Limit usage using this endpoint:
495+ Your current usage is exposed in the API response headers and via a dedicated endpoint:
478496 </p >
479497 <ul >
480498 <li >Anonymous: <a href =" { ' api_v1_rate_limit_usage' |alias} " >{ ' api_v1_rate_limit_usage' |alias} </a ></li >
481499 <li >Authenticated: <a href =" { ' api_v1_rate_limit_usage' |alias} ?secid=< ; secid_here> ; " >{ ' api_v1_rate_limit_usage' |alias} ?secid=< ; secid_here> ; </a ></li >
482500 </ul >
501+
483502 <pre ><code class =" language-xml" >{ $rate_limit_usage } </code ></pre >
503+
504+ <h5 >Example: 429 response</h5 >
505+ <pre ><code >HTTP/1.1 429 Too Many Requests
506+ Ratelimit-Limit: 750
507+ Ratelimit-Remaining: 0
508+ X-RateLimit-Limit: 750
509+ X-RateLimit-Remaining: 0
510+ X-RateLimit-Reset: 1725100800
511+ X-Ratelimit-Resource: API_V1_EXPORT2
512+ X-GK-Rate-Limit: API_V1_EXPORT2 0/750 (86400)
513+ X-GK-Rate-Limit-Exceeded: true
514+ Content-Type: application/xml</code ></pre >
515+ <pre ><code class =" language-xml" >{ $gk_xml_rate_limit_error } </code ></pre >
516+
517+ <h4 >Current API rate limits</h4 >
518+ <p >
519+ Your effective limit is the base multiplied by your tier multiplier (the <b >period</b > does not change):
520+ <code >effective_limit = floor(base_limit × tier_multiplier)</code >
521+ </p >
522+
523+ <table class =" table table-striped table-sm" >
524+ <caption class =" text-muted" style =" caption-side : bottom " >
525+ Endpoint quotas per tier (leaky bucket).
526+ </caption >
527+ <thead >
528+ <tr >
529+ <th >endpoint</th >
530+ <th >period_s</th >
531+ <th >base_limit</th >
532+ { foreach from= $smarty .const.RATE_LIMIT_LEVEL_MULTIPLIER key= tier item= mult}
533+ <th >{ $tier } (×{ $mult } )</th >
534+ { /foreach }
535+ </tr >
536+ </thead >
537+ <tbody >
538+ { foreach GK_RATE_LIMITS_DEFAULT as $limit => $values }
539+ { assign var= base value= $values [0]}
540+ { assign var= period value= $values [1]}
541+ <tr >
542+ <td >{ $limit } </td >
543+ <td >{ $period } </td >
544+ <td >{ $base } </td >
545+ { foreach from= $smarty .const.RATE_LIMIT_LEVEL_MULTIPLIER key= tier item= mult}
546+ <td >{ math equation= " floor(x*y)" x= $base y= $mult } </td >
547+ { /foreach }
548+ </tr >
549+ { /foreach }
550+ </tbody >
551+ </table >
552+
553+ <p class =" text-muted" >
554+ <em >Note: some endpoints (e.g. username changes) are account-only; anonymous rows are kept for consistency.</em >
555+ </p >
556+
557+ <h4 >Tiers and multipliers</h4 >
558+ <ul >
559+ <li ><b >Anonymous</b > — requests without an account or secure identifier; <b >counted by IP address</b > (×0.5).</li >
560+ <li ><b >User</b > — any logged-in account (×1).</li >
561+ <li ><b >Contributor</b > — merged code, documentation, translations, or issue triage (×2).</li >
562+ <li ><b >Donor</b > — active project sponsor (×2).</li >
563+ <li ><b >Recurring donor</b > — regular project sponsor (×3).</li >
564+ <li ><b >Maintainer</b > — core team and operational tasks (×3).</li >
565+ </ul >
566+
567+ <h4 >Tips to avoid 429s</h4 >
568+ <ul >
569+ <li >Authenticate when possible to avoid sharing anonymous (IP-based) limits behind NAT.</li >
570+ <li >Batch and paginate requests; add small client-side delays or jitter.</li >
571+ <li >Honor <code >Retry-After</code > and <code >X-RateLimit-*</code > headers when present.</li >
572+ </ul >
573+
574+ <h4 >How to earn higher limits</h4 >
575+ <ul >
576+ <li ><b >Code & ; QA:</b > bug fixes, features, security reports.</li >
577+ <li ><b >Community:</b > translations, documentation, user support, issue triage.</li >
578+ <li ><b >Sponsorship:</b > optional donations help cover hosting and maintenance.</li >
579+ </ul >
580+ <p >Once confirmed, your tier updates automatically (a short cache delay may apply). Non-financial contributions are valued equally.</p >
581+
582+ <h4 >Transparency</h4 >
583+ <ul >
584+ <li >The table lists <b >base limits</b > per endpoint and <b >multipliers</b > per tier.</li >
585+ <li >Endpoints may expose your current allowance and tier so you can monitor usage.</li >
586+ </ul >
587+
588+ <h4 >Abuse & ; fairness</h4 >
589+ <ul >
590+ <li >Automated abuse, credential sharing, or bypass attempts may lead to temporary or permanent restrictions.</li >
591+ <li >We aim to notify and work with users to resolve accidental overuse.</li >
592+ </ul >
593+
594+ <h4 >Privacy</h4 >
595+ <ul >
596+ <li >We store minimal counters in Redis keyed to anonymized identifiers.</li >
597+ <li >Anonymous usage is keyed by IP; authenticated usage is keyed to your account.</li >
598+ <li >Short-lived caches keep the service responsive.</li >
599+ </ul >
600+
601+ <h4 >Change management</h4 >
602+ <ul >
603+ <li >Base limits or multipliers may be adjusted to keep the service healthy; material changes are announced in the changelog/release notes.</li >
604+ <li >If you believe your tier is incorrect, please contact us for a review.</li >
605+ </ul >
606+
484607 </div >
485- <p >Current API rate limits are:</p >
486- <ul >
487- { foreach GK_RATE_LIMITS as $limit => $values }
488- <li >{ $limit }
489- <ul >
490- <li >max requests: { $values [0]} </li >
491- <li >period: { $values [1]} s</li >
492- </ul >
493- </li >
494- { /foreach }
495- </ul >
496608</div >
497609{ /block }
0 commit comments