Skip to main content

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.

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 q items per request: 100
  • Max total input characters (sum of all q items): 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​

StatusMeaningAction
200SuccessNo retry needed.
400Bad requestDo not retry. Fix the request (check limits, format, params).
401UnauthorizedDo not retry. Check API key.
429Rate limit / quotaRespect Retry-After header. Use exponential backoff starting at 1s.
502Upstream provider errorRetry once with the same request; the API automatically falls back across providers internally, so a 502 means every fallback also failed.
503Capacity saturated or circuit breaker openRetry with backoff.
5xxServer errorRetry with exponential backoff (1s, 2s, 4s). Max 3 attempts.
TimeoutNo responseRetry with exponential backoff. Consider increasing client timeout.

Response headers​

The API sets very few custom headers. The only one relevant to retry logic is:

HeaderWhenDescription
Retry-After429Seconds 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");
}