اکویار REST API · v1

مستندات API

تمام endpointها JSON می‌پذیرند و JSON برمی‌گردانند. پاسخ‌های خطا به سبک FastAPI هستند: { "detail": "..." }

شروع سریع

  • Base URL در حالت توسعه: http://localhost:3000/api
  • مسیرهای legacy هم فعال‌اند: POST /transcribe و POST /generate-report (دقیقاً مثل نسخه FastAPI).
  • CORS برای توسعه localhost فعال است.
  • کاربران ناشناس: هدر x-anon-token را با یک UUID ذخیره‌شده در localStorage بفرستید تا سهمیه‌تان شمرده شود.
  • سقف رایگان: ۳ درخواست (مجموع transcribe + generate-report). پس از آن: 403 {detail: "free_limit_reached"}

احراز هویت (JWT)

پس از register/login، توکن JWT هم در بدنه پاسخ برمی‌گردد و هم در کوکیhttpOnly ست می‌شود. برای کلاینت‌های API، هدر Bearer بفرستید:

Authorization: Bearer <token>

گذرواژه‌ها با bcrypt هش می‌شوند؛ توکن‌ها HS256 با انقضای ۳۰ روزه.

POST/api/auth/register

ساخت حساب کاربری جدید.

# Request curl -X POST /api/auth/register \ -H 'content-type: application/json' \ -d '{"email": "dr.sara@hospital.com", "password": "secret123"}' # 201 Response { "token": "eyJhbGciOiJIUzI1NiIs...", "user": { "id": 1, "email": "dr.sara@hospital.com", "is_pro": false } } # 409 { "detail": "email_already_registered" } # 422 { "detail": "password_too_short", "min": 6 }
POST/api/auth/login

ورود و دریافت توکن JWT.

curl -X POST /api/auth/login \ -H 'content-type: application/json' \ -d '{"email": "dr.sara@hospital.com", "password": "secret123"}' # 200 → { "token": "...", "user": { "id": 1, "email": "...", "is_pro": false } } # 401 → { "detail": "invalid_credentials" }
GET/api/usage

وضعیت سهمیه مصرفی کاربر فعلی یا کاربر ناشناس.

curl /api/usage # با کوکی JWT curl /api/usage -H 'x-anon-token: <uuid>' # ناشناس # 200 { "used": 2, "limit": 3, "is_free": true, "is_pro": false, "unlimited": false, "remaining": 1, "authenticated": false } # برای کاربران Pro: "limit": -1, "unlimited": true, "is_pro": true
POST/api/transcribe

نرمال‌سازی/رونویسی متن دیکته. در حالت استاندارد، مرورگر با Web Speech API متن را تولید می‌کند و این endpoint متن را نرمال می‌کند. اگرOPENAI_API_KEY تنظیم شده باشد، آپلود صوت (audio_base64) نیز پشتیبانی می‌شود.

curl -X POST /transcribe \ -H 'content-type: application/json' \ -H 'x-anon-token: <uuid>' \ -d '{"text": "كبد چرب گرید يك دارد", "language": "fa"}' # 200 { "transcription": "کبد چرب گرید یک دارد", "engine": "client+normalize" } # 403 { "detail": "free_limit_reached" }
POST/api/generate-report

تولید گزارش ساختاریافته رادیولوژی از روی متن دیکته.

curl -X POST /generate-report \ -H 'content-type: application/json' \ -H 'x-anon-token: <uuid>' \ -d '{ "transcription": "در لوب تحتانی ریه راست نودول 8 میلی متری دیده می شود. افیوژن وجود ندارد.", "modality": "CT", "body_part": "Chest", "clinical_info": "سرفه مزمن" }' # 200 → { "report": { "version": "1.0", "exam": { "modality": "CT", "body_part": "Chest", "exam_date": "2026-01-01T10:00:00.000Z", "language": "fa" }, "clinical_indication": "سرفه مزمن", "technique": "Thin-section axial CT acquisition ...", "comparison": "None available. ...", "findings": [ { "text": "...", "canonical": "nodule", "canonical_fa": "نودول", "severity": null, "laterality": "right", "category": "parenchyma", "abnormal": true } ], "normal_findings": [ "No pleural effusion (بدون افیوژن پلورال)" ], "impression": [ "1. right nodule — نودول سمت راست." ], "recommendations": [ "Clinical correlation recommended. ..." ], "disclaimer": "AI-assisted draft report — ..." } }
GET/api/reportsنیازمند JWT

فهرست گزارش‌های ذخیره‌شده کاربر (جدیدترین ابتدا).

curl /api/reports -H 'Authorization: Bearer <token>' # 200 → [ { "id": 12, "title": "CT Chest — نودول ریوی", "modality": "CT", "body_part": "Chest", "transcription": "...", "preview": "...", "created_at": "2026-01-01T10:00:00.000Z" } ]
POST/api/reportsنیازمند JWT

ذخیره گزارش جدید در داشبورد کاربر.

curl -X POST /api/reports -H 'Authorization: Bearer <token>' \ -H 'content-type: application/json' \ -d '{ "transcription": "...", "report_json": { ... }, "title": "CT Chest — نودول", "modality": "CT", "body_part": "Chest" }' # 201 → گزارش ذخیره‌شده به‌همراه id # 401 → { "detail": "not_authenticated" }
GET/api/reports/{id}نیازمند JWT

دریافت متن و JSON کامل یک گزارش (فقط مالک). DELETE همین مسیر گزارش را حذف می‌کند.

curl /api/reports/12 -H 'Authorization: Bearer <token>' # 200 | 404 curl -X DELETE /api/reports/12 -H 'Authorization: Bearer <token>' # → { "ok": true }
POST/api/contact

ثبت پیام در فرم تماس.

curl -X POST /api/contact -H 'content-type: application/json' \ -d '{"name": "دکتر رضایی", "email": "a@b.com", "message": "درخواست دمو برای بیمارستان"}' # 201 → { "ok": true, "id": 5 }

کدهای خطا

کدdetailمعنی
200/201—موفقیت
401not_authenticated / invalid_credentialsتوکن نامعتبر یا ورود ناموفق
403free_limit_reachedسهمیه رایگان تمام شده — نمایش مودال ثبت‌نام
404report_not_foundگزارش پیدا نشد یا مال شما نیست
409email_already_registeredایمیل تکراری
422validation_error / ...ورودی نامعتبر

نکته پیاده‌سازی (فرانت‌اند): در پاسخ 403 باdetail=free_limit_reached، مودال «Sign up to continue» را نمایش دهید — دقیقاً همان رفتار صفحه «اتاق گزارش».