API
Xatolar va idempotency
Error envelope, statuslar, retry va `Idempotency-Key` semantikasi.
Standart error envelope
JSON xato
{
"error": {
"code": "invalid_request",
"message": "So‘rov ma’lumotlari noto‘g‘ri.",
"type": "invalid_request_error"
},
"request_id": "req_…"
}User-facing xabarlar o‘zbekcha lokalizatsiya qilinadi. Ichki DB/provider tafsiloti klientga sizib chiqmaydi; correlation uchun request ID qaytariladi va logga yoziladi.
Muhim kodlar
| HTTP | Code | Klient harakati |
|---|---|---|
| 400 | invalid_request | Payload/capabilityni tuzating |
| 401 | invalid_api_key / api_key_expired / api_key_revoked | Yangi credential oling |
| 403 | insufficient_scope / model_not_allowed / ip_not_allowed / account_disabled | Siyosatni admin bilan hal qiling |
| 404 | not_found / model_not_found / file_not_found | ID/alias va ownershipni tekshiring |
| 409 | Conflict/idempotency in progress | Bir xil key bilan kutib retry qiling |
| 413 | Payload/file too large | Hajmni kamaytiring |
| 429 | usage_limit_exceeded | Retry-Afterni hurmat qiling |
| 502/503 | provider_error / unavailable | Retryable flag va backoff bo‘yicha qayta urinib ko‘ring |
| 500 | internal_error | Request ID bilan operatorga murojaat qiling |
Idempotency-Key
Machine inference mutationlarida barqaror, bitta mantiqiy amal uchun yagona key yuboring. Server user/key/route va request fingerprintini bog‘laydi. Bir xil key va bir xil payload yakunlangan bo‘lsa saqlangan status/header/body replay qilinadi; bir xil key boshqa payload bilan kelganda conflict qaytadi.
- Key’ni retrylar orasida o‘zgartirmang.
- Boshqa biznes amal uchun eski key’ni qayta ishlatmang.
- In-progress javobida
Retry-Afterbo‘lsa kuting. - Streaming javob ham replay uchun saqlanadi; ownership key principalga bog‘langan.
Retry strategiyasi
Soddalashtirilgan exponential backoff
for (let attempt = 0; attempt < 4; attempt++) {
const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"Idempotency-Key": operationId,
},
body: JSON.stringify(payload),
});
if (response.ok || ![409, 429, 502, 503].includes(response.status)) return response;
const retryAfter = Number(response.headers.get("retry-after") ?? 2 ** attempt);
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
}