REST API چیست؟ آموزش کامل طراحی و ساخت RESTful API با مثال عملی

REST API یکی از رایج‌ترین روش‌های ارتباط میان نرم‌افزارهاست. در این راهنمای عملی، اصول RESTful API، طراحی Endpoint، متدهای HTTP، مدیریت خطا، صفحه‌بندی و ساخت یک API واقعی متصل به درواره را یاد می‌گیرید.

Share
REST API چیست؟ آموزش کامل طراحی و ساخت RESTful API با مثال عملی

اگر یک وب‌سایت، اپلیکیشن موبایل، پنل مدیریتی، فروشگاه اینترنتی یا سرویس هوش مصنوعی ساخته باشید، احتمالاً با عبارت‌هایی مانند REST API، RESTful API، Endpoint، Request، Response و HTTP Method مواجه شده‌اید.

REST API یکی از رایج‌ترین روش‌های برقراری ارتباط میان نرم‌افزارهاست. فرانت‌اند یک درخواست برای سرور می‌فرستد، سرور درخواست را پردازش می‌کند و نتیجه را معمولاً در قالب JSON برمی‌گرداند.

اما REST فقط به معنی «ارسال JSON روی HTTP» نیست. REST یک سبک معماری برای طراحی سیستم‌های توزیع‌شده است و مجموعه‌ای از اصول را پیشنهاد می‌کند که رعایت آن‌ها باعث می‌شود API قابل‌فهم‌تر، مقیاس‌پذیرتر و نگهداری آن ساده‌تر شود.

در این مقاله، REST API را از مفاهیم پایه تا طراحی حرفه‌ای بررسی می‌کنیم و در پایان یک API واقعی با پایتون و FastAPI می‌سازیم که برای پردازش متن به API هوش مصنوعی درواره متصل می‌شود.

REST API چیست؟

REST مخفف Representational State Transfer است. این مفهوم در رساله دکتری Roy Fielding به‌عنوان یک سبک معماری برای سیستم‌های شبکه‌ای معرفی شد.

در معماری REST، داده‌ها و قابلیت‌های سیستم به شکل «منبع» یا Resource مدل‌سازی می‌شوند. هر منبع یک آدرس مشخص دارد و کلاینت با استفاده از متدهای استاندارد HTTP با آن تعامل می‌کند.

برای مثال، در یک فروشگاه اینترنتی می‌توانیم منابع زیر را داشته باشیم:

/users
/products
/orders
/categories

یک محصول مشخص نیز ممکن است با چنین آدرسی در دسترس باشد:

/products/42

درخواست زیر فهرست محصولات را دریافت می‌کند:

GET /products

درخواست زیر محصول شماره ۴۲ را دریافت می‌کند:

GET /products/42

درخواست زیر محصول جدیدی ایجاد می‌کند:

POST /products

نکته مهم این است که REST یک پروتکل مستقل، زبان برنامه‌نویسی یا فرمت فایل نیست. REST یک سبک معماری است که معمولاً روی HTTP پیاده‌سازی می‌شود.

تفاوت API، Web API، HTTP API و REST API

این اصطلاحات به یکدیگر نزدیک‌اند، اما دقیقاً یک معنی ندارند.

اصطلاحتعریف
APIرابطی برای ارتباط میان دو بخش نرم‌افزاری
Web APIیک API که از طریق شبکه و فناوری‌های وب در دسترس است
HTTP APIیک API که از پروتکل HTTP استفاده می‌کند
REST APIیک HTTP API که تا حد قابل‌قبولی از اصول معماری REST پیروی می‌کند
RESTful APIاصطلاحی برای API طراحی‌شده بر اساس اصول REST

هر REST API معمولاً یک HTTP API است، اما هر HTTP API الزاماً RESTful نیست.

برای مثال، این Endpoint از HTTP استفاده می‌کند:

POST /executeDeleteUser

اما طراحی آن Resource-oriented نیست و عمل حذف را هم در نام مسیر و هم در متد درخواست بیان می‌کند. شکل RESTful‌تر آن چنین است:

DELETE /users/42

Resource یا منبع چیست؟

Resource یکی از مهم‌ترین مفاهیم REST است. منبع چیزی است که API آن را مدیریت یا نمایش می‌دهد.

نمونه‌هایی از Resource عبارت‌اند از:

  • کاربر
  • محصول
  • سفارش
  • مقاله
  • پیام
  • فایل
  • گزارش
  • گفت‌وگوی هوش مصنوعی

هر منبع می‌تواند یک یا چند نمایش یا Representation داشته باشد. JSON رایج‌ترین قالب نمایش منابع در APIهای امروزی است، اما REST استفاده از JSON را اجباری نمی‌کند.

یک نمایش JSON از یک محصول ممکن است چنین باشد:

{
  "id": "prd_42",
  "name": "کیبورد مکانیکی",
  "price": 3500000,
  "currency": "IRR",
  "available": true
}

این JSON خود محصول نیست؛ بلکه نمایش داده‌ای آن محصول برای انتقال میان سرور و کلاینت است.

شش محدودیت اصلی معماری REST

برای آنکه یک معماری واقعاً به REST نزدیک باشد، باید محدودیت‌های اصلی آن را بشناسیم.

۱. جداسازی Client و Server

کلاینت و سرور مسئولیت‌های جداگانه دارند.

کلاینت معمولاً رابط کاربری و تجربه کاربر را مدیریت می‌کند. سرور مسئول داده‌ها، قوانین کسب‌وکار، احراز هویت و پردازش درخواست‌هاست.

این جداسازی اجازه می‌دهد فرانت‌اند و بک‌اند مستقل از یکدیگر توسعه پیدا کنند.

برای مثال، یک REST API می‌تواند هم‌زمان توسط موارد زیر استفاده شود:

  • وب‌سایت React
  • اپلیکیشن موبایل
  • پنل مدیریت
  • افزونه وردپرس
  • ابزار خط فرمان
  • سرویس خودکارسازی

۲. Stateless یا بدون وضعیت

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

برای مثال، اگر API از توکن دسترسی استفاده می‌کند، کلاینت باید آن را در هر درخواست ارسال کند:

Authorization: Bearer YOUR_ACCESS_TOKEN

Stateless بودن به این معنی نیست که سرور نمی‌تواند اطلاعات کاربران را در پایگاه داده ذخیره کند. منظور این است که درخواست مستقل از یک Session موقت روی یک سرور مشخص قابل پردازش باشد.

این ویژگی توزیع درخواست‌ها میان چند سرور را ساده‌تر می‌کند.

۳. Cacheable یا قابلیت کش شدن

پاسخ باید مشخص کند آیا قابلیت Cache شدن دارد یا خیر.

کش مناسب می‌تواند:

  • تعداد درخواست‌های تکراری را کاهش دهد
  • سرعت پاسخ‌گویی را افزایش دهد
  • مصرف پهنای باند را کم کند
  • بار سرور را کاهش دهد

هدرهایی مانند Cache-Control، ETag و Last-Modified برای کنترل Cache استفاده می‌شوند.

نمونه:

Cache-Control: public, max-age=300

این هدر اعلام می‌کند پاسخ می‌تواند تا ۳۰۰ ثانیه کش شود.

پاسخ‌های حاوی اطلاعات حساس یا شخصی نباید بدون سیاست مشخص Cache شوند.

۴. Uniform Interface یا رابط یکنواخت

رابط API باید قواعدی یکپارچه و قابل‌پیش‌بینی داشته باشد.

برای مثال:

  • منابع با URL مشخص می‌شوند
  • عملیات با متدهای HTTP بیان می‌شوند
  • پاسخ‌ها ساختار ثابت دارند
  • کدهای وضعیت HTTP به‌درستی استفاده می‌شوند
  • ارتباط میان منابع قابل فهم است

یک API یکنواخت باعث می‌شود توسعه‌دهنده مجبور نباشد رفتار هر Endpoint را از ابتدا حدس بزند.

۵. Layered System یا معماری لایه‌ای

کلاینت لازم نیست بداند مستقیماً با سرور اصلی ارتباط دارد یا درخواست از لایه‌های دیگری عبور می‌کند.

این لایه‌ها می‌توانند شامل موارد زیر باشند:

  • Load Balancer
  • Reverse Proxy
  • API Gateway
  • CDN
  • سیستم Cache
  • سرویس احراز هویت
  • سرویس مانیتورینگ

این ویژگی برای توسعه و مقیاس‌پذیری سامانه‌های بزرگ اهمیت زیادی دارد.

۶. Code on Demand

سرور در صورت نیاز می‌تواند کدی برای اجرا در کلاینت ارسال کند. این محدودیت اختیاری است و در بیشتر REST APIهای متداول نقش اصلی ندارد.

Endpoint چیست؟

Endpoint آدرس مشخصی در API است که کلاینت درخواست خود را برای آن ارسال می‌کند.

برای مثال:

https://api.example.com/v1/products

این آدرس از چند بخش تشکیل شده است:

https://api.example.com    Base URL
/v1                        API Version
/products                  Resource Path

در درواره، آدرس پایه API به شکل زیر است:

https://api.darvareh.ir/v1

Endpoint مربوط به Chat Completions نیز چنین است:

https://api.darvareh.ir/v1/chat/completions

طراحی صحیح URL در REST API

در طراحی مسیرها بهتر است نام منبع را بنویسیم، نه عملیاتی که قرار است انجام شود.

طراحی نامناسب:

/getAllUsers
/createNewUser
/updateUser
/deleteUser

طراحی مناسب‌تر:

/users
/users/{user_id}

متد HTTP نوع عملیات را مشخص می‌کند:

GET /users
POST /users
GET /users/42
PATCH /users/42
DELETE /users/42

از اسم استفاده کنید، نه فعل

مسیر زیر فعل دارد:

/createOrder

نسخه Resource-oriented آن:

/orders

ایجاد سفارش با متد POST مشخص می‌شود:

POST /orders

نام‌گذاری را یکپارچه نگه دارید

اگر برای منابع از حالت جمع استفاده می‌کنید، این قرارداد را در کل API رعایت کنید:

/users
/products
/orders
/articles

ترکیب نام‌های جمع و مفرد باعث ابهام می‌شود:

/user
/products
/order
/articles

REST اجبار رسمی برای جمع یا مفرد بودن نام‌ها ندارد؛ ثبات مهم‌تر از انتخاب یکی از این دو است.

روابط را با مسیر قابل‌فهم نمایش دهید

برای دریافت سفارش‌های یک کاربر می‌توان نوشت:

/users/42/orders

برای دریافت یک سفارش خاص:

/users/42/orders/981

با این حال، مسیرها را بیش از حد عمیق نکنید. مسیر زیر نگهداری سختی دارد:

/users/42/orders/981/items/5/reviews/17/comments

در بسیاری از موارد بهتر است منبع مقصد مستقیماً قابل دسترسی باشد:

/order-items/5
/reviews/17

از Query Parameter برای فیلتر و مرتب‌سازی استفاده کنید

نمونه فیلتر:

/products?category=laptop&available=true

نمونه مرتب‌سازی:

/products?sort=-created_at

علامت منفی می‌تواند نشان‌دهنده ترتیب نزولی باشد، البته این قرارداد باید در مستندات API توضیح داده شود.

نمونه جست‌وجو:

/articles?search=REST+API

نمونه انتخاب صفحه:

/articles?page=2&limit=20

متدهای HTTP در REST API

متد HTTP هدف درخواست را مشخص می‌کند.

متدکاربرد متداولنمونه
GETدریافت یک یا چند منبعGET /products
POSTایجاد منبع یا شروع یک پردازشPOST /products
PUTجایگزینی کامل منبعPUT /products/42
PATCHبه‌روزرسانی بخشی از منبعPATCH /products/42
DELETEحذف منبعDELETE /products/42
HEADدریافت هدرها بدون بدنه پاسخHEAD /products/42
OPTIONSدریافت قابلیت‌های ارتباطی EndpointOPTIONS /products

دریافت فهرست منابع با GET

GET /v1/articles?status=published&limit=20

پاسخ:

{
  "data": [
    {
      "id": "art_101",
      "title": "REST API چیست؟",
      "status": "published"
    },
    {
      "id": "art_102",
      "title": "آموزش HTTP",
      "status": "published"
    }
  ],
  "pagination": {
    "limit": 20,
    "next_cursor": null,
    "has_more": false
  }
}

درخواست GET نباید برای ایجاد، حذف یا تغییر داده استفاده شود.

ایجاد منبع با POST

POST /v1/articles
Content-Type: application/json

بدنه درخواست:

{
  "title": "آموزش طراحی REST API",
  "status": "draft"
}

پاسخ مناسب در صورت ایجاد منبع:

HTTP/1.1 201 Created
Location: /v1/articles/art_103
{
  "id": "art_103",
  "title": "آموزش طراحی REST API",
  "status": "draft"
}

جایگزینی کامل با PUT

PUT معمولاً برای جایگزینی کامل نمایش یک منبع استفاده می‌شود:

PUT /v1/articles/art_103
Content-Type: application/json
{
  "title": "راهنمای کامل REST API",
  "status": "published",
  "tags": ["api", "programming"]
}

اگر کلاینت فقط یک فیلد را ارسال کند، در یک طراحی مبتنی بر جایگزینی کامل ممکن است فیلدهای ارسال‌نشده حذف یا به مقدار پیش‌فرض بازگردانده شوند. رفتار دقیق باید در قرارداد API مشخص باشد.

به‌روزرسانی جزئی با PATCH

برای تغییر بخشی از یک منبع معمولاً PATCH مناسب‌تر است:

PATCH /v1/articles/art_103
Content-Type: application/json
{
  "status": "published"
}

حذف با DELETE

DELETE /v1/articles/art_103

اگر عملیات موفق باشد و بدنه‌ای برگردانده نشود، پاسخ زیر مناسب است:

HTTP/1.1 204 No Content

در پاسخ 204 نباید بدنه ارسال شود.

رابطه CRUD با متدهای HTTP

CRUD مخفف Create، Read، Update و Delete است.

عملیات CRUDمتد HTTP متداول
CreatePOST
ReadGET
Update کاملPUT
Update جزئیPATCH
DeleteDELETE

REST فقط معادل CRUD نیست. بعضی Endpointها عملیات محاسباتی، جست‌وجو، تولید محتوا یا اجرای Job انجام می‌دهند و الزاماً یک رکورد پایگاه داده را مدیریت نمی‌کنند.

برای مثال، درخواست تولید پاسخ هوش مصنوعی یک پردازش محاسباتی است:

POST /v1/chat/completions

Safe و Idempotent بودن متدها

در طراحی API باید با دو مفهوم مهم آشنا باشیم.

متد Safe

یک متد Safe نباید هدفش تغییر وضعیت سرور باشد. GET، HEAD و OPTIONS معمولاً Safe محسوب می‌شوند.

ممکن است سرور هنگام یک درخواست GET لاگ ثبت کند، اما این اثر جانبی نباید رفتار اصلی و مورد انتظار درخواست باشد.

متد Idempotent

اگر یک درخواست Idempotent چند بار با ورودی یکسان اجرا شود، اثر نهایی آن باید با یک بار اجرا شدن برابر باشد.

برای مثال:

DELETE /users/42

بار اول کاربر را حذف می‌کند. درخواست‌های بعدی ممکن است پاسخ 404 بدهند، اما اثر نهایی همچنان حذف بودن کاربر است.

به‌طور معمول:

متدSafeIdempotent
GETبلهبله
HEADبلهبله
PUTخیربله
DELETEخیربله
POSTخیرمعمولاً خیر
PATCHخیروابسته به پیاده‌سازی

جلوگیری از اجرای تکراری درخواست POST

فرض کنید کاربر دکمه پرداخت یا ثبت سفارش را دو بار فشار دهد. تکرار یک درخواست POST ممکن است دو سفارش ایجاد کند.

برای عملیات حساس می‌توان در APIهایی که از این قابلیت پشتیبانی می‌کنند از Idempotency Key استفاده کرد:

Idempotency-Key: order-7c8a2f51

سرور کلید را برای مدت مشخص نگه می‌دارد و درخواست تکراری با همان کلید را دوباره اجرا نمی‌کند.

وجود این قابلیت را نباید بدون بررسی مستندات یک API فرض کرد. همچنین Retry خودکار روی درخواست‌های غیر Idempotent باید با احتیاط انجام شود.

مهم‌ترین کدهای وضعیت در REST API

کد وضعیت HTTP نتیجه کلی درخواست را مشخص می‌کند.

پاسخ‌های موفق

کدمعنیکاربرد
200OKدرخواست با موفقیت پردازش شده است
201Createdمنبع جدید ایجاد شده است
202Acceptedدرخواست پذیرفته شده اما پردازش هنوز کامل نشده است
204No Contentعملیات موفق بوده و بدنه‌ای وجود ندارد

خطاهای سمت کلاینت

کدمعنیکاربرد
400Bad Requestساختار درخواست نامعتبر است
401Unauthorizedاطلاعات احراز هویت ارسال نشده یا معتبر نیست
403Forbiddenهویت مشخص است اما مجوز کافی وجود ندارد
404Not Foundمنبع پیدا نشده است
409Conflictدرخواست با وضعیت فعلی منبع تعارض دارد
415Unsupported Media Typeفرمت بدنه پشتیبانی نمی‌شود
422Unprocessable Contentساختار قابل خواندن است اما داده‌ها معتبر نیستند
429Too Many Requestsتعداد درخواست‌ها از محدودیت عبور کرده است

خطاهای سمت سرور یا سرویس بالادستی

کدمعنیکاربرد
500Internal Server Errorخطای داخلی پیش‌بینی‌نشده
502Bad Gatewayپاسخ نامعتبر از سرویس بالادستی
503Service Unavailableسرویس موقتاً در دسترس نیست
504Gateway Timeoutسرویس بالادستی در زمان مشخص پاسخ نداده است

بازگرداندن 200 OK برای تمام پاسخ‌ها و قراردادن خطا در بدنه، طراحی مناسبی نیست:

{
  "success": false,
  "error": "User not found"
}

اگر منبع پیدا نشده است، پاسخ باید کد 404 داشته باشد تا مرورگر، SDK، Proxy، سیستم مانیتورینگ و کلاینت بتوانند آن را درست تفسیر کنند.

طراحی ساختار استاندارد خطا

ساختار خطا باید ثابت، قابل‌پردازش و برای توسعه‌دهنده قابل‌فهم باشد.

نمونه پیشنهادی:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "اطلاعات ارسال‌شده معتبر نیست.",
    "details": [
      {
        "field": "email",
        "reason": "فرمت ایمیل صحیح نیست."
      }
    ],
    "request_id": "req_f71b8c2a"
  }
}

هر بخش هدف مشخصی دارد:

  • code: کد پایدار و قابل‌پردازش برای نرم‌افزار
  • message: توضیح قابل‌خواندن برای توسعه‌دهنده یا کاربر
  • details: جزئیات فیلدهای نامعتبر
  • request_id: شناسه‌ای برای پیگیری درخواست در لاگ‌ها

نام کلاس، Stack Trace، Query پایگاه داده، مسیر فایل و اطلاعات داخلی سرور را در پاسخ عمومی نمایش ندهید.

Validation یا اعتبارسنجی درخواست

اعتبارسنجی فقط بررسی وجود فیلدها نیست. می‌توان آن را در چند سطح انجام داد.

اعتبارسنجی ساختار

{
  "email": "user@example.com",
  "age": 30
}

در این مرحله بررسی می‌شود که:

  • email رشته باشد
  • age عدد صحیح باشد
  • فیلدهای ضروری وجود داشته باشند

اعتبارسنجی محدودیت‌ها

برای مثال:

  • عنوان حداقل ۵ کاراکتر باشد
  • تعداد آیتم‌ها از ۱۰۰ بیشتر نباشد
  • تاریخ پایان قبل از تاریخ شروع نباشد

اعتبارسنجی قوانین کسب‌وکار

برای مثال:

  • محصول موجود باشد
  • سفارش قبلاً لغو نشده باشد
  • نام کاربری تکراری نباشد
  • کاربر مجوز انجام عملیات را داشته باشد

اگر خروجی مدل هوش مصنوعی در یک فرایند نرم‌افزاری استفاده می‌شود، آن خروجی نیز باید پیش از ذخیره یا اجرای عملیات اعتبارسنجی شود.

طراحی Pagination یا صفحه‌بندی

بازگرداندن هزاران رکورد در یک پاسخ باعث افزایش زمان پاسخ، مصرف حافظه و هزینه شبکه می‌شود.

دو روش رایج برای صفحه‌بندی وجود دارد.

صفحه‌بندی Offset-based

/articles?offset=40&limit=20

یا:

/articles?page=3&limit=20

مزایا:

  • پیاده‌سازی ساده
  • امکان رفتن مستقیم به یک صفحه
  • مناسب برای داده‌های کوچک و نسبتاً ثابت

معایب:

  • در داده‌های بزرگ ممکن است کند شود
  • با اضافه یا حذف شدن رکوردها احتمال جابه‌جایی نتایج وجود دارد

صفحه‌بندی Cursor-based

/articles?limit=20&cursor=eyJpZCI6MTAwfQ

پاسخ:

{
  "data": [
    {
      "id": "art_101",
      "title": "REST API چیست؟"
    }
  ],
  "pagination": {
    "next_cursor": "eyJpZCI6MTAxfQ",
    "has_more": true
  }
}

مزایا:

  • مناسب برای داده‌های بزرگ
  • رفتار پایدارتر هنگام اضافه شدن رکوردهای جدید
  • کارایی بهتر برای Feed و پیمایش پیوسته

معایب:

  • رفتن مستقیم به صفحه دلخواه دشوارتر است
  • پیاده‌سازی سمت سرور پیچیده‌تر می‌شود
معیارOffsetCursor
سادگی پیاده‌سازیبیشترکمتر
مناسب داده بزرگمتوسطبله
رفتن مستقیم به صفحهبلهمعمولاً خیر
پایداری در داده متغیرکمتربیشتر
مناسب Infinite Scrollمتوسطبله

فیلتر، جست‌وجو و مرتب‌سازی

بهتر است قرارداد مشخصی برای Query Parameterها تعریف کنید.

فیلتر:

/orders?status=paid

چند فیلتر:

/orders?status=paid&currency=IRR

مرتب‌سازی نزولی بر اساس زمان ایجاد:

/orders?sort=-created_at

مرتب‌سازی چندگانه:

/orders?sort=-created_at,total

جست‌وجو:

/articles?search=هوش+مصنوعی

محدود کردن فیلدهای پاسخ:

/users?fields=id,name,email

همه پارامترها، مقادیر مجاز، مقدار پیش‌فرض و حداکثر Limit باید در مستندات API ثبت شوند.

نسخه‌بندی REST API

تغییرات ناسازگار می‌توانند کلاینت‌های قبلی را از کار بیندازند. نسخه‌بندی به API اجازه می‌دهد تغییرات بزرگ را کنترل کند.

یکی از روش‌های رایج، قرار دادن نسخه در URL است:

https://api.example.com/v1/products

نسخه بعدی:

https://api.example.com/v2/products

درواره نیز نسخه API را در URL قرار می‌دهد:

https://api.darvareh.ir/v1

روش دیگر استفاده از Header است:

Accept: application/vnd.example.v2+json

هیچ روش واحدی برای تمام پروژه‌ها بهترین نیست. مهم این است که قرارداد انتخاب‌شده:

  • واضح باشد
  • در تمام Endpointها رعایت شود
  • تاریخ توقف نسخه‌های قدیمی اعلام شود
  • تغییرات ناسازگار بدون نسخه جدید منتشر نشوند

اضافه کردن یک فیلد اختیاری معمولاً تغییر سازگار است، اما حذف یا تغییر نوع یک فیلد می‌تواند Breaking Change باشد.

REST API و JSON چه ارتباطی دارند؟

بیشتر REST APIهای مدرن از JSON استفاده می‌کنند، زیرا:

  • برای انسان نسبتاً خواناست
  • تقریباً در تمام زبان‌ها پشتیبانی می‌شود
  • نسبت به XML ساختار فشرده‌تری دارد
  • برای وب و اپلیکیشن موبایل مناسب است

درخواست JSON معمولاً این هدر را دارد:

Content-Type: application/json

کلاینت می‌تواند قالب پاسخ مورد انتظار را اعلام کند:

Accept: application/json

REST به JSON محدود نیست و می‌تواند از XML، متن، تصویر، فایل باینری یا فرمت‌های دیگر استفاده کند.

اتصال به REST API هوش مصنوعی درواره

درواره یک زیرساخت API برای دسترسی برنامه‌نویسی به مدل‌های هوش مصنوعی است. آدرس پایه API:

https://api.darvareh.ir/v1

نمونه درخواست به Chat Completions:

curl --request POST \
  --url https://api.darvareh.ir/v1/chat/completions \
  --header "Authorization: Bearer YOUR_DARVAREH_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "YOUR_MODEL_ID",
    "messages": [
      {
        "role": "system",
        "content": "پاسخ‌ها را دقیق، کوتاه و به زبان فارسی بنویس."
      },
      {
        "role": "user",
        "content": "REST API را در سه جمله توضیح بده."
      }
    ]
  }'

در این درخواست:

  • متد POST برای ارسال ورودی پردازشی استفاده شده است
  • هدر Authorization کلید API را حمل می‌کند
  • Content-Type قالب JSON را مشخص می‌کند
  • model شناسه مدل درواره است
  • messages پیام‌های ورودی مدل را مشخص می‌کند

برای مشاهده مدل‌های در دسترس و قیمت به‌روز آن‌ها، صفحه مدل‌ها و قیمت‌های درواره را بررسی کنید.

ساخت REST API با FastAPI و اتصال آن به درواره

در این بخش یک سرویس خلاصه‌سازی متن می‌سازیم. کلاینت متن را به API ما می‌فرستد، بک‌اند آن را به درواره ارسال می‌کند و خلاصه را برمی‌گرداند.

این معماری یک مزیت مهم دارد: کلید درواره فقط در بک‌اند قرار می‌گیرد و وارد مرورگر یا اپلیکیشن عمومی نمی‌شود.

ساختار ساده پروژه:

rest-summary-api/
├── app.py
├── requirements.txt
└── .env

ایجاد محیط مجازی

در لینوکس و macOS:

python -m venv .venv
source .venv/bin/activate

در ویندوز PowerShell:

python -m venv .venv
.venv\Scripts\Activate.ps1

نصب وابستگی‌ها

فایل requirements.txt:

fastapi
uvicorn[standard]
httpx
python-dotenv

سپس اجرا کنید:

pip install -r requirements.txt

تنظیم متغیرهای محیطی

فایل .env:

DARVAREH_API_KEY=YOUR_DARVAREH_API_KEY
DARVAREH_MODEL_ID=YOUR_MODEL_ID

فایل .env را در مخزن عمومی Git قرار ندهید. آن را به .gitignore اضافه کنید:

.env
.venv/
__pycache__/

نوشتن کد API

فایل app.py:

import os

import httpx
from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field

load_dotenv()

DARVAREH_API_KEY = os.getenv("DARVAREH_API_KEY")
DARVAREH_MODEL_ID = os.getenv("DARVAREH_MODEL_ID")
DARVAREH_URL = "https://api.darvareh.ir/v1/chat/completions"

if not DARVAREH_API_KEY:
    raise RuntimeError("متغیر DARVAREH_API_KEY تنظیم نشده است.")

if not DARVAREH_MODEL_ID:
    raise RuntimeError("متغیر DARVAREH_MODEL_ID تنظیم نشده است.")

app = FastAPI(
    title="Persian Summary API",
    version="1.0.0",
    description="REST API ساده برای خلاصه‌سازی متن فارسی با درواره",
)


class SummaryRequest(BaseModel):
    text: str = Field(
        min_length=20,
        max_length=10_000,
        description="متنی که باید خلاصه شود",
    )
    max_sentences: int = Field(
        default=3,
        ge=1,
        le=10,
        description="حداکثر تعداد جمله‌های خلاصه",
    )


class SummaryResponse(BaseModel):
    summary: str
    model: str


class HealthResponse(BaseModel):
    status: str


@app.get("/health", response_model=HealthResponse)
async def health_check():
    return {"status": "ok"}


@app.post("/v1/summaries", response_model=SummaryResponse)
async def create_summary(payload: SummaryRequest):
    request_body = {
        "model": DARVAREH_MODEL_ID,
        "messages": [
            {
                "role": "system",
                "content": (
                    "تو یک ویراستار فارسی هستی. "
                    "متن ورودی را دقیق و بدون افزودن اطلاعات جدید خلاصه کن."
                ),
            },
            {
                "role": "user",
                "content": (
                    f"متن زیر را حداکثر در {payload.max_sentences} جمله "
                    f"خلاصه کن:\n\n{payload.text}"
                ),
            },
        ],
    }

    headers = {
        "Authorization": f"Bearer {DARVAREH_API_KEY}",
        "Content-Type": "application/json",
    }

    timeout = httpx.Timeout(
        connect=10.0,
        read=60.0,
        write=20.0,
        pool=10.0,
    )

    try:
        async with httpx.AsyncClient(timeout=timeout) as client:
            response = await client.post(
                DARVAREH_URL,
                headers=headers,
                json=request_body,
            )
    except httpx.TimeoutException as exc:
        raise HTTPException(
            status_code=504,
            detail={
                "code": "UPSTREAM_TIMEOUT",
                "message": "سرویس هوش مصنوعی در زمان تعیین‌شده پاسخ نداد.",
            },
        ) from exc
    except httpx.RequestError as exc:
        raise HTTPException(
            status_code=502,
            detail={
                "code": "UPSTREAM_CONNECTION_ERROR",
                "message": "ارتباط با سرویس هوش مصنوعی برقرار نشد.",
            },
        ) from exc

    if response.status_code == 429:
        raise HTTPException(
            status_code=503,
            detail={
                "code": "UPSTREAM_RATE_LIMIT",
                "message": "سرویس موقتاً با محدودیت درخواست مواجه شده است.",
            },
        )

    if response.status_code >= 500:
        raise HTTPException(
            status_code=502,
            detail={
                "code": "UPSTREAM_ERROR",
                "message": "سرویس هوش مصنوعی پاسخ معتبری برنگرداند.",
            },
        )

    if response.status_code >= 400:
        raise HTTPException(
            status_code=502,
            detail={
                "code": "UPSTREAM_REQUEST_REJECTED",
                "message": "درخواست توسط سرویس بالادستی پذیرفته نشد.",
            },
        )

    try:
        result = response.json()
        summary = result["choices"][0]["message"]["content"].strip()
    except (ValueError, KeyError, IndexError, TypeError) as exc:
        raise HTTPException(
            status_code=502,
            detail={
                "code": "INVALID_UPSTREAM_RESPONSE",
                "message": "ساختار پاسخ سرویس هوش مصنوعی معتبر نبود.",
            },
        ) from exc

    if not summary:
        raise HTTPException(
            status_code=502,
            detail={
                "code": "EMPTY_UPSTREAM_RESPONSE",
                "message": "سرویس هوش مصنوعی پاسخ خالی برگرداند.",
            },
        )

    return SummaryResponse(
        summary=summary,
        model=DARVAREH_MODEL_ID,
    )

اجرای REST API

uvicorn app:app --reload

سرویس به‌صورت پیش‌فرض روی آدرس زیر اجرا می‌شود:

http://127.0.0.1:8000

مستندات تعاملی FastAPI نیز در این آدرس در دسترس است:

http://127.0.0.1:8000/docs

آزمایش Health Check

curl http://127.0.0.1:8000/health

پاسخ:

{
  "status": "ok"
}

ارسال درخواست خلاصه‌سازی

curl --request POST \
  --url http://127.0.0.1:8000/v1/summaries \
  --header "Content-Type: application/json" \
  --data '{
    "text": "REST یک سبک معماری برای طراحی سیستم‌های توزیع‌شده است. در این معماری منابع با URL مشخص می‌شوند و کلاینت با استفاده از متدهای HTTP با آن‌ها تعامل می‌کند. طراحی درست REST API باعث می‌شود ارتباط میان سرویس‌ها قابل‌فهم‌تر و نگهداری آن ساده‌تر شود.",
    "max_sentences": 2
  }'

نمونه پاسخ:

{
  "summary": "REST یک سبک معماری برای طراحی سیستم‌های توزیع‌شده است که منابع را از طریق URL و متدهای HTTP در دسترس قرار می‌دهد. رعایت اصول آن به ساخت APIهای قابل‌فهم و نگهداری‌پذیر کمک می‌کند.",
  "model": "YOUR_MODEL_ID"
}

مقدار واقعی model همان شناسه‌ای خواهد بود که در فایل .env تنظیم کرده‌اید.

چرا درخواست مستقیم از فرانت‌اند مناسب نیست؟

قرار دادن کلید API در JavaScript مرورگر باعث می‌شود کاربران بتوانند آن را از ابزارهای توسعه مرورگر، فایل‌های Bundle یا درخواست‌های شبکه استخراج کنند.

طراحی نامناسب:

const apiKey = "YOUR_DARVAREH_API_KEY";

حتی اگر کد Minify یا Obfuscate شود، کلید همچنان قابل بازیابی است؛ زیرا مرورگر برای ارسال درخواست باید به مقدار واقعی آن دسترسی داشته باشد.

معماری مناسب‌تر:

مرورگر یا اپلیکیشن
        ↓
بک‌اند شما
        ↓
API درواره
        ↓
مدل هوش مصنوعی

بک‌اند شما می‌تواند:

  • کلید API را محرمانه نگه دارد
  • ورودی‌ها را اعتبارسنجی کند
  • محدودیت نرخ درخواست اعمال کند
  • هزینه مصرف را کنترل کند
  • Timeout و Retry را مدیریت کند
  • خروجی مدل را بررسی کند
  • لاگ و شناسه پیگیری تولید کند

Timeout در REST API

هر درخواست شبکه باید Timeout مشخص داشته باشد. بدون Timeout ممکن است Worker یا Connection برای مدت نامحدود منتظر بماند.

بهتر است Timeoutها جداگانه تنظیم شوند:

  • Connect Timeout: زمان برقراری اتصال
  • Read Timeout: زمان انتظار برای دریافت پاسخ
  • Write Timeout: زمان ارسال درخواست
  • Pool Timeout: زمان انتظار برای دریافت اتصال از Pool

مقدار مناسب به نوع عملیات بستگی دارد. یک درخواست ساده پایگاه داده با تولید محتوای هوش مصنوعی زمان پاسخ یکسانی ندارد.

Retry را چگونه پیاده‌سازی کنیم؟

Retry برای خطاهای موقت مفید است، اما نباید هر خطایی را بدون محدودیت تکرار کرد.

موارد مناسب‌تر برای Retry:

  • خطای موقت شبکه
  • 502 Bad Gateway
  • 503 Service Unavailable
  • 504 Gateway Timeout
  • در برخی شرایط 429 Too Many Requests

موارد نامناسب:

  • بیشتر خطاهای 400
  • کلید نامعتبر
  • ورودی نامعتبر
  • منبع پیدا نشده
  • درخواست POST غیر Idempotent بدون سازوکار جلوگیری از تکرار

بین تلاش‌ها از Exponential Backoff استفاده کنید:

تلاش اول: بدون تأخیر
تلاش دوم: حدود ۱ ثانیه
تلاش سوم: حدود ۲ ثانیه
تلاش چهارم: حدود ۴ ثانیه

برای جلوگیری از Retry هم‌زمان تعداد زیادی کلاینت، مقداری Jitter یا تأخیر تصادفی نیز اضافه می‌شود.

پردازش هم‌زمان و غیرهم‌زمان

بعضی عملیات سریع‌اند و می‌توان نتیجه را در همان پاسخ برگرداند. بعضی عملیات مانند پردازش فایل بزرگ، تولید ویدئو یا اجرای گزارش طولانی بهتر است به Job تبدیل شوند.

نمونه ایجاد Job:

POST /v1/jobs

پاسخ:

HTTP/1.1 202 Accepted
{
  "id": "job_8451",
  "status": "queued",
  "status_url": "/v1/jobs/job_8451"
}

کلاینت می‌تواند وضعیت را بررسی کند:

GET /v1/jobs/job_8451

پاسخ در زمان پردازش:

{
  "id": "job_8451",
  "status": "processing"
}

پاسخ بعد از پایان:

{
  "id": "job_8451",
  "status": "completed",
  "result_url": "/v1/results/result_992"
}

برای کاربردهای بلادرنگ می‌توان از Streaming استفاده کرد، اما برای Jobهای طولانی معمولاً Polling کنترل‌شده یا Webhook مناسب‌تر است.

مستندسازی REST API با OpenAPI

OpenAPI یک قالب استاندارد برای توصیف APIهای HTTP است. با OpenAPI می‌توان موارد زیر را مشخص کرد:

  • مسیرها
  • متدها
  • پارامترها
  • ساختار درخواست
  • ساختار پاسخ
  • روش احراز هویت
  • کدهای خطا
  • Schema داده‌ها

نمونه ساده:

openapi: 3.1.0
info:
  title: Persian Summary API
  version: 1.0.0

paths:
  /v1/summaries:
    post:
      summary: خلاصه‌سازی متن فارسی
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - text
              properties:
                text:
                  type: string
                  minLength: 20
                  maxLength: 10000
                max_sentences:
                  type: integer
                  minimum: 1
                  maximum: 10
                  default: 3
      responses:
        "200":
          description: خلاصه با موفقیت تولید شد
          content:
            application/json:
              schema:
                type: object
                required:
                  - summary
                  - model
                properties:
                  summary:
                    type: string
                  model:
                    type: string
        "422":
          description: داده ورودی معتبر نیست
        "502":
          description: پاسخ سرویس بالادستی معتبر نبود
        "504":
          description: سرویس بالادستی در زمان تعیین‌شده پاسخ نداد

OpenAPI و REST یک مفهوم نیستند:

  • REST سبک معماری است
  • OpenAPI قالب توصیف قرارداد API است

یک API می‌تواند RESTful باشد اما سند OpenAPI نداشته باشد. همچنین می‌توان یک HTTP API غیر RESTful را با OpenAPI مستند کرد.

REST API در مقایسه با GraphQL و RPC

REST تنها روش طراحی API نیست.

معیارRESTGraphQLRPC
محور طراحیResourceSchema و Queryعملیات و Function
مسیرهامعمولاً چند Endpointاغلب یک Endpointمسیرهای عملیاتی
انتخاب فیلدهاتحت کنترل سرور یا Query Parameterتحت کنترل کلاینتوابسته به قرارداد
Cache مبتنی بر HTTPساده‌ترنیازمند طراحی بیشتروابسته به پیاده‌سازی
یادگیری اولیهنسبتاً سادهمتوسطنسبتاً ساده
مناسب برایAPI عمومی، CRUD، وب و موبایلداده‌های مرتبط و نیازهای متغیر UIعملیات مشخص و سرویس‌های داخلی

REST انتخاب خوبی است اگر:

  • منابع مشخصی دارید
  • می‌خواهید از قابلیت‌های استاندارد HTTP استفاده کنید
  • سادگی ابزارها و سازگاری گسترده مهم است
  • API عمومی یا چندکلاینتی می‌سازید

GraphQL می‌تواند مناسب‌تر باشد اگر کلاینت‌ها به ترکیب‌های متفاوتی از داده‌های مرتبط نیاز دارند.

RPC برای عملیات مشخصی مانند generateReport یا calculatePrice گاهی بیان طبیعی‌تری دارد. هدف، انتخاب معماری متناسب با مسئله است؛ نه RESTful نشان دادن اجباری تمام عملیات.

آیا Chat Completions یک REST API خالص است؟

در دنیای واقعی بسیاری از APIها از HTTP، JSON، URL نسخه‌بندی‌شده و قراردادهای استاندارد استفاده می‌کنند، اما تمام عملیاتشان دقیقاً به CRUD روی منابع پایدار محدود نیست.

Endpoint زیر یک پردازش تولید متن را اجرا می‌کند:

POST /v1/chat/completions

می‌توان آن را یک HTTP API سازگار با الگوی رایج سرویس‌های هوش مصنوعی دانست. REST یک طیف از رعایت محدودیت‌های معماری است و استفاده از واژه RESTful نباید باعث شود کیفیت قرارداد، ثبات Schema و تجربه توسعه‌دهنده نادیده گرفته شود.

اشتباهات رایج در طراحی REST API

استفاده از فعل در تمام URLها

نامناسب:

/getProducts
/createProduct
/updateProduct

مناسب‌تر:

/products
/products/{product_id}

استفاده از GET برای تغییر داده

نامناسب:

GET /users/42/delete

این درخواست ممکن است توسط Cache، Crawler یا ابزارهای پیش‌بارگذاری فراخوانی شود.

مناسب:

DELETE /users/42

برگرداندن کد ۲۰۰ برای همه‌چیز

کد وضعیت باید نتیجه واقعی درخواست را نشان دهد. برای منبع ناموجود 404 و برای اعتبارسنجی ناموفق 400 یا 422 مناسب‌تر است.

تغییر مداوم ساختار خطا

اگر یک Endpoint فیلد message و دیگری error_text برگرداند، کلاینت مجبور می‌شود برای هر مسیر منطق جداگانه بنویسد.

نداشتن محدودیت برای فهرست‌ها

Endpoint زیر نباید بدون محدودیت میلیون‌ها رکورد برگرداند:

GET /events

برای فهرست‌های بزرگ Pagination و حداکثر Limit تعریف کنید.

افشای ساختار پایگاه داده

API نباید صرفاً نسخه اینترنتی جدول‌های پایگاه داده باشد. مدل عمومی API باید بر اساس نیاز مصرف‌کننده طراحی شود، نه جزئیات داخلی ذخیره‌سازی.

وابسته کردن کلاینت به ترتیب فیلدهای JSON

ترتیب اعضای Object در JSON نباید بخشی از قرارداد API محسوب شود. کلاینت باید فیلدها را بر اساس نام بخواند.

نبود Timeout

درخواست بدون Timeout می‌تواند منابع سرور را برای زمان نامحدود اشغال کند.

Retry کورکورانه

تکرار بی‌قیدوشرط درخواست POST ممکن است عملیات را چند بار اجرا کند.

قرار دادن کلید API در فرانت‌اند

کلید سرویس‌های بیرونی باید در بک‌اند، Secret Manager یا متغیر محیطی نگهداری شود.

بازگرداندن مستقیم خروجی مدل

اگر خروجی هوش مصنوعی قرار است وارد پایگاه داده یا فرایند دیگری شود، باید Schema، طول، نوع و مقادیر مجاز آن اعتبارسنجی شود.

چک‌لیست طراحی RESTful API

پیش از انتشار API این موارد را بررسی کنید:

  • منابع اصلی سیستم مشخص شده‌اند
  • URLها بر اساس اسم منابع طراحی شده‌اند
  • نام‌گذاری مسیرها یکپارچه است
  • متدهای HTTP معنای درست دارند
  • GET برای تغییر داده استفاده نشده است
  • کدهای وضعیت واقعی برگردانده می‌شوند
  • ساختار خطا ثابت است
  • تمام ورودی‌ها اعتبارسنجی می‌شوند
  • فهرست‌های بزرگ Pagination دارند
  • فیلتر و مرتب‌سازی قرارداد مشخص دارند
  • نسخه API مشخص است
  • تغییرات ناسازگار مدیریت می‌شوند
  • Timeout برای درخواست‌های خروجی تنظیم شده است
  • Retry فقط برای شرایط مناسب انجام می‌شود
  • کلید API در فرانت‌اند قرار ندارد
  • اطلاعات داخلی در خطاها افشا نمی‌شود
  • مستندات OpenAPI یا معادل آن وجود دارد
  • نمونه درخواست و پاسخ واقعی ارائه شده است
  • API روی ورودی‌ها و پاسخ‌های نامعتبر آزمایش شده است
  • لاگ‌ها دارای Request ID هستند
  • مدل و قیمت سرویس‌های مصرفی از منبع به‌روز بررسی می‌شوند

پرسش‌های متداول

REST API چه تفاوتی با RESTful API دارد؟

در کاربرد روزمره این دو اصطلاح اغلب به جای یکدیگر استفاده می‌شوند. RESTful معمولاً تأکید می‌کند که API بر اساس محدودیت‌ها و اصول REST طراحی شده است.

آیا REST یک پروتکل است؟

خیر. REST یک سبک معماری است. بیشتر REST APIها از HTTP استفاده می‌کنند، اما REST با HTTP یکسان نیست.

آیا REST API حتماً باید JSON برگرداند؟

خیر. JSON رایج‌ترین قالب است، اما REST می‌تواند XML، متن، تصویر یا داده باینری نیز منتقل کند.

آیا هر API مبتنی بر HTTP یک REST API است؟

خیر. یک API ممکن است از HTTP استفاده کند اما ساختار آن RPC، GraphQL یا یک قرارداد اختصاصی باشد.

تفاوت PUT و PATCH چیست؟

PUT معمولاً برای جایگزینی کامل نمایش یک منبع و PATCH برای تغییر جزئی آن استفاده می‌شود. رفتار دقیق هر دو باید در مستندات API مشخص شود.

تفاوت POST و PUT چیست؟

POST معمولاً منبعی با شناسه تعیین‌شده توسط سرور ایجاد می‌کند یا یک پردازش را شروع می‌کند. PUT اغلب برای ایجاد یا جایگزینی کامل منبع در یک URI مشخص استفاده می‌شود و معمولاً Idempotent است.

آیا GET می‌تواند بدنه داشته باشد؟

وابسته کردن API به بدنه GET انتخاب مناسبی نیست. بسیاری از ابزارها، Cacheها و واسطه‌ها رفتار قابل‌اتکایی برای آن ارائه نمی‌کنند. برای پارامترهای دریافت داده از URL و Query Parameter استفاده کنید.

برای ساخت REST API چه زبانی مناسب است؟

REST به زبان خاصی وابسته نیست. می‌توانید از Python، JavaScript، TypeScript، PHP، Java، Go، C# یا زبان‌های دیگر استفاده کنید. انتخاب زبان به تیم، زیرساخت و نیاز پروژه بستگی دارد.

آیا FastAPI فقط برای هوش مصنوعی است؟

خیر. FastAPI یک فریم‌ورک عمومی برای ساخت API با پایتون است، اما به دلیل پشتیبانی مناسب از Type Hint، Validation، Async و OpenAPI در پروژه‌های هوش مصنوعی نیز محبوب است.

آدرس API درواره چیست؟

Base URL درواره:

https://api.darvareh.ir/v1

Endpoint مربوط به Chat Completions:

https://api.darvareh.ir/v1/chat/completions

از کجا شناسه و قیمت مدل‌ها را ببینیم؟

برای مشاهده مدل‌های قابل استفاده، Model ID و قیمت به‌روز، صفحه مدل‌های درواره را بررسی کنید.

جمع‌بندی

REST API یک روش ساده اما قدرتمند برای طراحی ارتباط میان نرم‌افزارهاست. یک API خوب فقط مجموعه‌ای از URLها نیست؛ بلکه قراردادی پایدار، قابل‌پیش‌بینی و مستند میان سرور و کلاینت است.

برای طراحی یک RESTful API حرفه‌ای باید منابع را درست مدل کنید، از متدها و کدهای وضعیت HTTP با معنای واقعی آن‌ها استفاده کنید، ورودی‌ها را اعتبارسنجی کنید، پاسخ خطا را یکپارچه نگه دارید و برای Pagination، Versioning، Timeout و تغییرات ناسازگار برنامه داشته باشید.

اگر قصد دارید قابلیت‌هایی مانند چت، خلاصه‌سازی، تولید محتوا، تحلیل متن یا پردازش هوشمند را به REST API خود اضافه کنید، می‌توانید از زیرساخت API درواره استفاده کنید. کلید را در بک‌اند نگه دارید، مدل مناسب را بر اساس کیفیت و هزینه انتخاب کنید و خروجی مدل را قبل از استفاده در فرایندهای نرم‌افزاری اعتبارسنجی کنید.

برای شروع، وارد وب‌سایت درواره شوید و مدل‌ها و قیمت‌های به‌روز را در صفحه مدل‌های درواره مشاهده کنید.

منابع رسمی

مقالات مرتبط

برای مطالعه شرایط استفاده و محدودیت‌های مسئولیت، صفحه «سلب مسئولیت» را مشاهده کنید.

Read more

اتوماسیون هوش مصنوعی چیست؟ کاربردها و آموزش ساخت AI Automation

اتوماسیون هوش مصنوعی چیست؟ کاربردها و آموزش ساخت AI Automation

اتوماسیون هوش مصنوعی با ترکیب گردش‌کارهای خودکار و مدل‌های هوش مصنوعی، پردازش متن، دسته‌بندی، استخراج اطلاعات و تصمیم‌های پیشنهادی را خودکار می‌کند. در این راهنما، معماری و ساخت نمونه عملی آن با API درواره را می‌آموزید.

Agentic Commerce چیست؟ آینده خرید با ایجنت هوش مصنوعی

Agentic Commerce چیست؟ آینده خرید با ایجنت هوش مصنوعی

Agentic Commerce شیوه‌ای جدید برای خرید اینترنتی است که در آن ایجنت هوش مصنوعی می‌تواند نیاز کاربر را بفهمد، محصولات را جست‌وجو و مقایسه کند و فرایند خرید را پیش ببرد. در این راهنما با معماری، UCP، ACP و پیاده‌سازی آن با API درواره آشنا می‌شوید.