پرش به محتویات

قرارداد API درخواست OTP

این صفحه Context مصرف Endpoint را تکمیل می‌کند. Schema ماشینی و منبع حقیقت نهایی در backend/api/openapi/identity.yaml قرار دارد.

مشخصات

فیلد مقدار
عملیات ساخت OTP Challenge
Method و Path POST /api/v1/auth/otp/challenges
وضعیت Beta
احراز هویت ندارد
پاسخ موفق 202 Accepted
Cache no-store
Idempotency الزامی
Header الزام Rule
Content-Type الزامی application/json؛ Parameter معتبر مانند Charset پذیرفته می‌شود
Idempotency-Key الزامی رشته UTF-8 با طول 16 تا 128 و Entropy بالا
X-Device-ID الزامی UUID تصادفی و پایدار برای نصب App یا Browser

X-Device-ID شناسه حساب یا Device Fingerprint مخفی نیست. Client آن را یک‌بار تصادفی می‌سازد، برای همان نصب پایدار نگه می‌دارد و به‌عنوان Credential استفاده نمی‌کند.

Request

{
  "mobile": "09121234567"
}

Object بسته است؛ Field ناشناخته، Body دوم، JSON نامعتبر یا Mobile خارج از طول ساختاری رد می‌شود. اعتبارسنجی واقعی قالب Mobile در Domain انجام می‌شود.

Response موفق

{
  "challengeId": "0198b2ad-5687-7abc-8def-0123456789ab",
  "maskedMobile": "0912****567",
  "expiresAt": "2026-08-15T12:02:00Z",
  "resendAvailableAt": "2026-08-15T12:01:00Z"
}

Header Location مسیر Canonical Challenge را برمی‌گرداند. پاسخ درباره وجود Account اطلاعاتی نمی‌دهد.

خطاها

HTTP Code علت Retry
400 invalid_request Header، JSON یا Shape نامعتبر پس از اصلاح Request
409 idempotency_conflict استفاده Key برای Intent متفاوت خیر؛ Key جدید برای Intent جدید
415 unsupported_media_type Media Type غیر JSON پس از اصلاح Header
422 invalid_mobile شماره موبایل ایران نامعتبر پس از اصلاح Mobile
429 otp_rate_limited عبور از کنترل سوءاستفاده پس از Retry-After
503 otp_challenge_unavailable عدم پذیرش پایدار یا تحویل Retry محدود با Backoff

پاسخ خطا از application/problem+json، Code انگلیسی پایدار و requestId استفاده می‌کند. متن قابل نمایش باید با UX Writing محصول فارسی و امن باشد. پیاده‌سازی Bootstrap هنوز Detailهای انگلیسی دارد؛ این مورد پیش از اتصال UI یک Gap باز و نیازمند اصلاح هم‌زمان OpenAPI، Test و Handler است.

Retry و شبکه ضعیف

  • Retry همان Intent باید همان Idempotency-Key را نگه دارد.
  • Timeout یا قطع پاسخ به معنی شکست قطعی نیست؛ Client ابتدا همان Request را با Key قبلی تکرار می‌کند.
  • 4xx به‌جز 429 خودکار Retry نمی‌شود.
  • 429 از Retry-After و 503 از Backoff نمایی محدود با Jitter پیروی می‌کند.

نمونه محلی

$headers = @{
  "Idempotency-Key" = "local-otp-request-000001"
  "X-Device-ID" = "0670e315-183a-4fd9-aa80-bf2f7b275063"
}
Invoke-RestMethod `
  -Method Post `
  -Uri "http://localhost:8080/api/v1/auth/otp/challenges" `
  -ContentType "application/json" `
  -Headers $headers `
  -Body '{"mobile":"09121234567"}'