Timeout & Retry Guide
This guide covers how Langbly handles timeouts, what client settings to use, and how to implement retry logic.
Server Processing Timeout​
A real client request to POST /language/translate/v2 is given a 60 second server-side deadline for the translation call itself. There is no client-configurable override for this: no request header changes it, and the API does not return a custom timeout header telling you what deadline was applied.
Recommended Client Timeout​
Set your HTTP client timeout to 75 seconds, giving a margin above the server's own 60s deadline for network overhead.
In practice, most requests complete in 1-5 seconds. The 75s figure is a ceiling to guard against a hung connection, not an expectation of normal latency.
Character Limits​
- Max
qitems per request: 100 - Max total input characters (sum of all
qitems): 200,000
These limits are the same for every account regardless of plan; there is no higher limit to unlock at a paid tier. Exceeding either returns 400 INVALID_ARGUMENT. See Limits and timeouts for the full reference.
Retry Strategy​
| Status | Meaning | Action |
|---|---|---|
| 200 | Success | No retry needed. |
| 400 | Bad request | Do not retry. Fix the request (check limits, format, params). |
| 401 | Unauthorized | Do not retry. Check API key. |
| 429 | Rate limit / quota | Respect Retry-After header. Use exponential backoff starting at 1s. |
| 502 | Upstream provider error | Retry once with the same request; the API automatically falls back across providers internally, so a 502 means every fallback also failed. |
| 503 | Capacity saturated or circuit breaker open | Retry with backoff. |
| 5xx | Server error | Retry with exponential backoff (1s, 2s, 4s). Max 3 attempts. |
| Timeout | No response | Retry with exponential backoff. Consider increasing client timeout. |
Response headers​
The API sets very few custom headers. The only one relevant to retry logic is:
| Header | When | Description |
|---|---|---|
Retry-After | 429 | Seconds to wait before retrying |
Do not build retry or rate-limiting logic around any other x-* header; the API does not send request-id, processing-time, character-count, provider, or cache-status headers. Read the actual JSON error envelope (see Errors) for diagnostic detail instead.
Code Examples​
C# (.NET HttpClient)​
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient { Timeout = TimeSpan.FromSeconds(75) };
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
async Task<string> TranslateWithRetry(string text, string target, int maxRetries = 3)
{
for (int attempt = 0; attempt < maxRetries; attempt++)
{
try
{
var payload = new { q = text, target };
var content = new StringContent(
JsonSerializer.Serialize(payload),
Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://api.langbly.com/language/translate/v2", content);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
return result;
}
if ((int)response.StatusCode == 429 || (int)response.StatusCode == 503)
{
var retryAfter = response.Headers.RetryAfter?.Delta
?? TimeSpan.FromSeconds(Math.Pow(2, attempt));
await Task.Delay(retryAfter);
continue;
}
if ((int)response.StatusCode == 400 || (int)response.StatusCode == 401)
throw new Exception($"Non-retriable error: {response.StatusCode}");
// 502 or 5xx: retry once
if (attempt == 0) continue;
throw new Exception($"Server error: {response.StatusCode}");
}
catch (TaskCanceledException) when (attempt < maxRetries - 1)
{
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}
}
throw new Exception("Max retries exceeded");
}
Python (requests)​
import requests
import time
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.langbly.com/language/translate/v2"
def translate_with_retry(text: str, target: str, max_retries: int = 3) -> dict:
for attempt in range(max_retries):
try:
response = requests.post(
BASE_URL,
json={"q": text, "target": target},
headers={"x-api-key": API_KEY},
timeout=75,
)
if response.ok:
return response.json()
if response.status_code in (429, 503):
retry_after = int(response.headers.get("Retry-After", 2 ** attempt))
time.sleep(retry_after)
continue
if response.status_code in (400, 401):
raise ValueError(f"Non-retriable: {response.status_code} {response.text}")
# 502/5xx: retry
if attempt == 0:
continue
response.raise_for_status()
except requests.Timeout:
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
continue
raise
raise RuntimeError("Max retries exceeded")
JavaScript (fetch)​
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://api.langbly.com/language/translate/v2";
async function translateWithRetry(text, target, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 75000);
const response = await fetch(BASE_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY,
},
body: JSON.stringify({ q: text, target }),
signal: controller.signal,
});
clearTimeout(timeout);
if (response.ok) return response.json();
if (response.status === 429 || response.status === 503) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "1");
await new Promise((r) => setTimeout(r, retryAfter * 1000));
continue;
}
if (response.status === 400 || response.status === 401) {
throw new Error(`Non-retriable: ${response.status}`);
}
if (attempt === 0) continue; // retry 502/5xx once
throw new Error(`Server error: ${response.status}`);
} catch (err) {
if (err.name === "AbortError" && attempt < maxRetries - 1) {
await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
continue;
}
throw err;
}
}
throw new Error("Max retries exceeded");
}