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

SettingValueDescription
REQUEST_TIMEOUT_MS60,000 msMaximum server-side processing time per request
Per-LLM-call timeoutDynamic8s base + 1s per 500 chars (max 60s)

The server enforces an absolute deadline via AbortController. The request deadline auto-scales with input text length: short texts use the 60s base, but longer texts automatically get up to 120s. The per-LLM-call timeout also scales (8s base + 1s per 500 chars, max 90s). You never need to configure anything — the system adapts to your text size.

Client Timeout Override

You can control the server-side deadline per request using the x-timeout-ms request header:

HeaderTypeDefaultMax
x-timeout-msinteger (ms)60,000120,000

Example: send x-timeout-ms: 90000 to allow up to 90 seconds for a long text.

Set your HTTP client timeout to 90 seconds.

This accounts for worst-case scenarios:

  • ~12s permit acquisition (during high load)
  • ~60s LLM response (long text)
  • ~10s network overhead + safety margin

In practice, most requests complete in 1-5 seconds. The 90s timeout is a ceiling, not an expectation.

Character Limits by Plan

PlanMax chars per requestHeader
Trial / Free10,000x-chars-limit: 10000
Pay-As-You-Go50,000x-chars-limit: 50000
API Paid (Starter/Growth/Scale)100,000x-chars-limit: 100000

The x-chars-limit header is included in every response so your client can auto-configure.

Retry Strategy

StatusMeaningAction
200SuccessNo retry needed. Check x-quality-warning header for quality notes.
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.
502Translation failedRetry once with the same request.
503Capacity saturatedRespect Retry-After header. Retry after the indicated seconds.
504Gateway TimeoutRetry with exponential backoff. Consider sending x-timeout-ms: 90000 header for long texts.
5xxServer errorRetry with exponential backoff (1s, 2s, 4s). Max 3 attempts.
TimeoutNo responseRetry with exponential backoff. Consider increasing client timeout.

Response Headers Reference

The following headers are included on every response — both success (200) and error (400, 502, 503, 504). They are always present, not only when an error occurs. A timeout is reflected in the HTTP status code (504), while x-timeout-ms always shows the configured deadline.

Always-present headers:

HeaderExampleDescription
x-request-idabc-123-defUnique request identifier for support
x-processing-time-ms3842Server-side processing time in milliseconds
x-timeout-ms60000Effective server timeout (default or from x-timeout-ms request header)
x-chars-in1976Total input characters processed
x-chars-out2104Total output characters produced
x-chars-limit10000Your plan's character limit per request
x-providergeminiTranslation provider used
x-cache-statushit or missWhether response came from cache

Conditional headers:

HeaderWhenDescription
x-quality-warningQuality gate failedtrue when translation has known quality issues
x-quality-checks-failedQuality gate failedComma-separated list of failed checks
x-glossary-entries-totalGlossary usedTotal glossary entries provided
x-glossary-entries-matchedGlossary usedEntries that matched input text
Retry-After429 or 503Seconds to wait before retrying

Code Examples

C# (.NET HttpClient)

using System.Net.Http;
using System.Text;
using System.Text.Json;

var client = new HttpClient { Timeout = TimeSpan.FromSeconds(90) };
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=90,
)

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(), 90000);

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