# API کاتالوگ، بازار و راهنما

قرارداد واقعی مسیرهای عمومی و رفتار خطا بدون نیاز به کلید کاربر.

وضعیت: پیاده‌سازی‌شده | مخاطب: توسعه‌دهندگان
بازبینی مستندات: ۲۰۲۶/۰۹/۲۴ · ۲ مهر ۱۴۰۵

## قواعد مشترک

این‌ها مسیرهای برنامهٔ مارکت‌پلیس‌اند، نه یک API معاملهٔ عمومی دارای کلید توسعه‌دهنده. پاسخ‌های JSON از کمک‌تابع مشترک با Cache-Control:no-store و X-Content-Type-Options:nosniff تولید می‌شوند.

مقادیر دهدهی قیمت و حجم بازار رشته‌اند تا دقت آن‌ها حفظ شود. GETهای جدول زیر ورود نمی‌خواهند؛ POSTهای راهنما و برآورد، کنترل Origin هم‌مبدأ دارند.

## مسیرها و وضعیت HTTP

| روش و مسیر | ورودی / دسترسی | موفقیت و خطا |
| --- | --- | --- |
| GET /api/catalog | عمومی؛ بدون پارامتر پیش‌نمایش | 200 با Catalog؛ حتی هنگام ناموجود بودن، mode=unavailable در بدنه است. |
| GET /api/markets/wallex | عمومی؛ بدون symbol | 200 در status=ready؛ 503 در unavailable. |
| GET /api/markets/wallex?symbol=USDTTMN | عمومی؛ یکی از پنج نماد مجاز | 400 برای نماد نامعتبر؛ جزئیات معتبر 200 و پرچم‌های وجود داده. |
| GET /api/markets/exchange-rate | عمومی؛ سیاست روی سرور خوانده می‌شود | 200 برای ready؛ 503 برای unavailable. |
| POST /api/quote | Origin هم‌مبدأ؛ سفارش قابل اجرا ندارد | 403 برای Origin نامعتبر؛ در غیر این صورت همیشه 503. |
| POST /api/assistant | بدنهٔ JSON {message}؛ در حالت AI نشست لازم است | 200 با reply/mode؛ 400 پیام نامعتبر، 401 نیاز به ورود، 403 Origin و 503 اختلال. |

## قرارداد کاتالوگ

بدنه شامل projects، content و mode است. mode یکی از live، preview یا unavailable است. Project فیلدهای id، slug، category، status، عنوان‌ها و توضیح‌های محلی، symbol، image_url، unit_price_rial، duration_months، total_units، sold_units، documents و شاخص نمونهٔ اختیاری دارد.

Content شامل معرفی هیرو، FAQ، فوتر، عنوان منوها، نشانی اختیاری اپلیکیشن و پذیرش توکنایزیشن، نشان تجاری و enabled_locales است. دادهٔ شخصی مشتری جزو این قرارداد نیست.

```javascript
const response = await fetch('/api/catalog');
const catalog = await response.json();
if (catalog.mode === 'unavailable') {
  console.log('فهرست اکنون در دسترس نیست');
} else {
  console.log(catalog.projects.map(({slug, symbol}) => ({slug, symbol})));
}
```

## قرارداد مظنه و جزئیات

Feed شامل source:wallex، status، quotes، receivedAt و در خطا error است. هر Quote شامل symbol، base، name، price، change24h، volume24h، quoteVolume24h، high24h، low24h، amountPrecision، pricePrecision، spot، otc و receivedAt است؛ چند فیلد عددی می‌توانند null باشند.

جزئیات شامل symbol، receivedAt، candles با time/close، asks و bids با price/quantity، historyAvailable و depthAvailable است. خطای منبع نمودار یا عمق، لزوماً HTTP503 نمی‌دهد؛ برنامه می‌تواند HTTP200 با پرچم false و آرایهٔ خالی دریافت کند. دادهٔ ناموجود را از همین پرچم‌ها تشخیص دهید.

## قرارداد نرخ مرجع

پاسخ آماده شامل status:ready، base:USDT، quote:IRR، rateRial، rateToman، receivedAt و expiresAt است. پاسخ ناموجود شامل status:unavailable، همان base/quote و error است.

سیاست پیش‌فرض single با والکس است. آداپتورهای فعلی والکس و نوبیتکس‌اند؛ میانگین، میانگین حسابی هم‌وزن منابع انتخابی و وابسته به تازگی همهٔ آن‌هاست. نرخ نهایی به نزدیک‌ترین ریال گرد می‌شود.

```javascript
const response = await fetch('/api/markets/exchange-rate');
const rate = await response.json();
if (response.ok && rate.status === 'ready') {
  console.log(rate.rateToman, rate.expiresAt);
}
// بدون دادهٔ معتبر، نرخ جایگزین نسازید.
```

## پیش‌نمایش و نبود مسیر سفارش

پارامتر preview=design فقط در صفحات و محیط توسعه برای کاتالوگ نمونه کاربرد دارد و /api/catalog را به دادهٔ نمونهٔ اجباری تبدیل نمی‌کند. شکست خواندن کاتالوگ متصل با نمونه جبران نمی‌شود.

POST /api/quote هیچ قرارداد اجرایی مقدار/قیمت یا سفارش نهایی ندارد. تا زمان پیاده‌سازی سرویس معامله، 503 پاسخ مورد انتظار این مسیر است؛ نباید با retry نامحدود آن را به سفارش واقعی تبدیل کرد.

## مراجع پیاده‌سازی

- app/api/catalog/route.ts
- app/api/markets/wallex/route.ts
- app/api/markets/exchange-rate/route.ts
- app/api/quote/route.ts
- app/api/assistant/route.ts
- lib/server.ts
- lib/wallex.ts
- lib/exchange-rate.ts
