تلاش مجدد و Idempotency
از اجرای تکراری درخواست پولی در قطع اتصال و خطا جلوگیری کنید.
یک شناسه برای یک تصمیم کاربر
در درخواستهای تغییردهنده هدر Idempotency-Key بفرستید. مقدار میتواند ۱ تا ۱۲۸ نویسه از حرف، عدد، نقطه، خط تیره، زیرخط یا دونقطه باشد. برای هر درخواست منطقی، کلید را یک بار بسازید و در تمام retryهای همان درخواست حفظ کنید.
Idempotency-Key: order-summary-2026-0001چه چیزی یکسان است؟
کلید idempotency در محدودهٔ کلید API بررسی میشود. روش HTTP، مسیر، query و JSON باید یکسان باشند؛ ترتیب فیلدهای JSON را نیز در retry حفظ کنید. تغییر ورودی با همان کلید به IDEMPOTENCY_CONFLICT با HTTP 409 منجر میشود. چرخاندن کلید API محدودهٔ تازهای میسازد.
پاسخ درخواست تکراری
اگر پاسخ JSON کوچکتر از یک میلیون بایت، در ۲۴ ساعت اخیر قابل بازیابی باشد، همان پاسخ با Idempotency-Replayed: true و شناسهٔ قبلی برمیگردد. اگر کار در حال اجراست یا نتیجهٔ بزرگ/جریانی قابل replay نیست، 409 با REQUEST_ALREADY_ACCEPTED و شناسهٔ قبلی میگیرید. این پاسخ کار جدیدی آغاز نمیکند.
تصمیم درست در خطا
در 400 ورودی را اصلاح کنید. در 401 کلید را بررسی کنید. در 402 موجودی/سقف را حل کنید. در 429 با تأخیر و jitter تلاش کنید. در قطع ارتباط یا خطای نامطمئن، همان idempotency را حفظ کنید؛ تا تعیین وضعیت، کلید تازه نسازید. شناسهٔ قدیمی را از /v1/requests/{id} بررسی کنید.
محدودیت نگهداری
محتوای پاسخ برای replay فقط ۲۴ ساعت نگهداری میشود. رکورد درخواست برای جلوگیری از تکرار و گزارش مالی باقی میماند. بعد از این بازه، همان کلید کار را دوباره اجرا نمیکند و ممکن است فقط شناسهٔ درخواست قبلی را برگرداند. فایلهای حجیم را هنگام دریافت در سیستم خود نگه دارید.
import json, os, urllib.request, urllib.error
payload = {
"model": "z-ai/glm-5.3-flash",
"input": "سلام! در یک جمله خودت را معرفی کن.",
"max_output_tokens": 512
}
request = urllib.request.Request(
"https://api.sarovi.ir/v1/responses",
data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
headers={
"Authorization": "Bearer " + os.environ["SAROVI_API_KEY"],
"Idempotency-Key": "your-stable-request-id",
"Content-Type": "application/json"
},
method="POST"
)
try:
with urllib.request.urlopen(request, timeout=300) as response:
result = json.load(response)
print(result)
except urllib.error.HTTPError as error:
detail = json.load(error)
raise RuntimeError(f"{error.code}: {detail['error'].get('code', detail['error'].get('type', 'HTTP_ERROR'))}") from errorکلید را در متغیر محیطی SAROVI_API_KEY قرار بده. بدون نصب کتابخانه؛ با Python استاندارد.
قرارداد API 1.6.0 · تاریخچهٔ تغییرات