LinkHarbor API’si dakikada kaç isteğe izin verir, bir istek ne kadar büyük olabilir, başlıklar nasıl okunur ve bir 429 nasıl doğru ele alınır.
API’yi herkes için hızlı tutmak için LinkHarbor dakika başına istek sayısını sınırlar. Limitler planına bağlı değildir – aylık bir API çağrısı kotası yoktur. Bu makale tüm limitleri listeler ve kodunun bunları nasıl temiz şekilde ele alabileceğini gösterir.
İstekler nasıl sayılır
- Her istek tam olarak bir kovaya düşer, örneğin kimliği doğrulanmış istekler için user veya token değişimi için token
- Sayım tam dakika başına yapılır (UTC); sayaç her yeni dakikada sıfırdan başlar
- Kovaya göre API çalışma alanı, kişi, bağlantı veya IP adresi başına sayar
- Daha token, kapsam veya şema aşamasında başarısız olan istekler (401, 403 insufficient_scope, 400, şema kontrolünden gelen 422 validation_failed) sayılmaz; 403 feature_not_available gibi sonraki hatalar sayılır
Tüm limitler
| Kova (X-RateLimit-Bucket) | Limit | Sayım birimi | Geçerli olduğu |
|---|---|---|---|
| user | Dakikada 600 | API anahtarlarından gelen token’lar için çalışma alanı (çalışma alanının tüm anahtarları ve yapay zekâ araçları birlikte); panel girişleri için kişi | Kendi kovası olmayan /v1’e yapılan tüm kimliği doğrulanmış istekler |
| token | Dakikada 30 | IP adresi | POST /v1/token |
| public | Dakikada 120 | IP adresi | GET /v1/plans ve GET /v1/pages/available gibi kimlik doğrulamasız API istekleri |
| callback | Dakikada 120 | IP adresi | POST /v1/callbacks/sale |
| internal | Dakikada 120 | IP adresi | “Custom (API)” entegrasyonunun Ingest URL’si (POST /v1/ingest/{id}) |
| mcp | Dakikada 120 | Yapay zekâ bağlantısı (erişim token’ı) | /mcp adresindeki MCP sunucusu |
| oauth | Dakikada 300 | IP adresi | Yapay zekâ asistanları için OAuth girişi ve keşif |
| auth | Dakikada 30 | IP adresi | Giriş, kayıt, şifre sıfırlama (panel ve uygulama) |
| refresh | Dakikada 120 | IP adresi | Bir panel oturumunu uzatma |
| discover | Dakikada 60 | Kişi, giriş yapılmamışsa IP adresi | Uygulamanın Keşfet bölümü |
| subs_read | Dakikada 120 | Kişi, giriş yapılmamışsa IP adresi | Takip ettiğin sayfaları okuma (uygulama) |
| subs_write | Dakikada 20 | Kişi, giriş yapılmamışsa IP adresi | Takip ettiğin sayfaları değiştirme (uygulama) |
Çalışma alanı başına bir bütçe
Aynı çalışma alanındaki API anahtarlarından gelen tüm token’lar dakikada 600 isteği paylaşır – kaç anahtar oluşturduğundan bağımsız olarak. Bağlı yapay zekâ asistanlarının araçları da API’yi dahili olarak çağırdıkları için burada sayılır. Yani daha fazla anahtar limiti artırmaz. Çok fazla yük birkaç programa dağılıyorsa ortak bütçeye göre planla.
Başlıklar
- X-RateLimit-Limit
- Kovanın dakika başına limiti, örneğin 600.
- X-RateLimit-Remaining
- Geçerli dakikada kaç istek kaldığı.
- X-RateLimit-Bucket
- İsteğin düştüğü kova, örneğin user.
- Retry-After
- Yalnızca 429 rate_limited ile: sonraki dakikanın başlamasına kalan saniye. api_key_locked ile bekleme süresi details.retry_after_sec içindedir.
Limite ulaşıldığında
Limite ulaşıldığında API HTTP 429 ve bu gövdeyle yanıt verir. message içindeki metin hesap dilindedir (bkz. API hata biçimi), burada İngilizce. rate_limited koduna güven:
HTTP/1.1 429 Too Many Requests
Retry-After: 37
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Bucket: user
{ "error": "rate_limited", "message": "Too many requests. Please try again in a moment.", "retry_after_sec": 37 } - Retry-After veya retry_after_sec değerini oku
- En az o kadar saniye bekle, tüm işlemler aynı anda yeniden başlamasın diye biraz rastgelelik ekleyerek
- İsteği en fazla birkaç kez yeniden dene
- Sürekli 429 alıyorsan işi daha uzun bir süreye yay
const BASE = 'https://dock.at-harbor.com';
let cached = null; // { token, expiresAt }
async function getToken() {
if (cached && Date.now() < cached.expiresAt - 60_000) return cached.token;
const res = await fetch(BASE + '/v1/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
key_id: process.env.LH_KEY_ID,
key_secret: process.env.LH_KEY_SECRET,
}),
});
if (!res.ok) throw new Error('Token exchange failed: HTTP ' + res.status);
const data = await res.json();
cached = { token: data.token, expiresAt: Date.now() + data.expires_in * 1000 };
return cached.token;
}
async function lh(method, path, body, attempt = 0) {
const headers = { Authorization: 'Bearer ' + (await getToken()) };
if (body !== undefined) headers['Content-Type'] = 'application/json';
const res = await fetch(BASE + path, {
method,
headers,
body: body === undefined ? undefined : JSON.stringify(body),
});
if (res.status === 429 && attempt < 3) {
const wait = Number(res.headers.get('Retry-After') ?? 5);
await new Promise((r) => setTimeout(r, (wait + Math.random() * 2) * 1000));
return lh(method, path, body, attempt + 1);
}
if (res.status === 401 && attempt === 0) {
cached = null; // token’ın süresi doldu – yeni bir token’la bir kez daha dene
return lh(method, path, body, attempt + 1);
}
const data = await res.json().catch(() => null);
if (!res.ok) throw new Error((data && data.error) + ' (HTTP ' + res.status + ')');
return data;
}
// Örnek: const { items } = await lh('GET', '/v1/pages'); Büyük veri miktarları için ipuçları
- Token’ı önbelleğe al ve yalnızca 15 dakika sonra süresi dolmadan kısa süre önce yenile
- X-RateLimit-Remaining değerini izle ve azaldığında yavaşla
- İstekleri düzinelerce paralel bağlantı yerine art arda gönder
- Listeleri her sayfayı tek tek sorgulamak yerine bir kez yükle ve yerel olarak filtrele
- Büyük senkronizasyonları birkaç dakikaya yay
- 5xx hatalarını artan aralarla yeniden dene, ama 4xx hatalarını deneme
Diğer limitler
| Ne | Limit | Yanıt |
|---|---|---|
| Başarısız girişler | E-posta adresi ve IP başına 5, 10 ve 20 hatalı denemeden sonra kilitleme: 60 saniye, 5 dakika, 30 dakika | 429 account_locked |
| Form gönderimleri | Tüm formlar genelinde saatte ve IP adresi başına 10 | 429 form_rate_limited |
Token değişimindeki hatalı denemeler anahtarı ve IP’yi geçici olarak kilitler, bkz. API anahtarları ve token’lar. Anlık bildirimleri yalnızca panelde gönderirsin; limitleri Takipçiler ve anlık bildirimler bölümünde anlatılıyor.
Planının içerik limitleri – sayfalar, bağlantılar, bloklar, kısa bağlantılar vb. – hız limiti değil sabit üst sınırlardır. Planların karşılaştırması bölümünde listeleniyor.
İstek boyutu
Her gövde API onu okumadan önce ölçülür. Ne kadar büyük olabileceği uç noktaya bağlıdır:
| Uç noktalar | En büyük gövde |
|---|---|
| Giriş, kayıt ve /v1/auth altındaki diğer kimlik doğrulamasız çağrılar, POST /v1/token, POST /v1/oauth/exchange, /oauth altındaki yapay zekâ asistanları için OAuth uç noktaları ve bunların onayı, POST /v1/ingest/{id}, Destekle bloğunun ödeme sayfası, uygulamanın abonelik çağrıları (takip, koleksiyonlar, anlık bildirim cihazları), çalışma alanı değiştirme, POST /v1/auth/logout-all, hesap silme, iki faktör kurulumu, bir daveti kabul etme, ortaklık programını etkinleştirme ve bir entegrasyonu bağlarken dönüş adımı | 64 KB |
| Bir sayfada form gönderme dahil diğer tüm JSON uç noktaları | 1 MB |
| POST /v1/webhooks/{id}/verify-signature ve /mcp adresindeki MCP sunucusu | 2 MB |
| Dosya yüklemeleri (POST /v1/assets ve POST /v1/pages/{id}/uploads, multipart/form-data) | Tüm istek için 11 MB, dosyanın kendisi en fazla 10 MB |
Gövde daha büyükse API 413 request_too_large ile yanıt verir; details.max_bytes ve details.max_kb limiti belirtir. Bir yüklemede çok büyük bir dosya 413 payload_too_large ile sonuçlanır. DELETE çağrıları gibi gövdesiz uç noktalar gövde kabul etmez ya da yalnızca {} kabul eder.
HTTP/1.1 413 Payload Too Large
{ "error": "request_too_large", "message": "…", "details": { "max_bytes": 65536, "max_kb": 64 }, "request_id": "…" } Gövdenin içinde de limitler vardır: her metnin bir azami uzunluğu, her listenin bir azami giriş sayısı vardır ve bilinmeyen alanlar reddedilir. Değerler API referansında uç nokta başına listelenir. Bir ihlal 422 validation_failed ile sonuçlanır ve details alanı, kuralı ve limiti belirtir. Bir isteğin yolu ve sorgu dizesi birlikte en fazla 16 KB uzunluğunda olabilir.
Bunlar da işine yarayabilir
Bir şey bulamadın mı?
Neye ihtiyacın olduğunu bize anlat, destek ekibimiz sana kişisel olarak yardımcı olsun.