۱. دربارهی این راهنما
این سند راهنمای فنی یکپارچهسازی سرویس B2B هموست برای سازمانهای شریک است. هدف آن این است که تیم فنی شما بتواند با کمترین تلاش، سامانهی خود را به API این سرویس متصل کند، برای کاربران نهایی خود کیفپول دارایی بسازد و معاملات خرید و فروش را ثبت نماید.
با این API میتوانید:
- فهرست داراییهای قابل ارائه و قیمتهای لحظهای آنها را دریافت کنید.
- برای هر کاربر نهایی خود یک کیفپول دارایی ایجاد و مدیریت کنید.
- سفارش خرید یا فروش دارایی برای کاربران ثبت کنید و مقدار توکن منتقلشده را در پاسخ بگیرید.
- تاریخچهی تراکنشهای خرید و فروش را برای حسابرسی و نمایش به کاربر استخراج کنید.
- موجودی کلی کیفپول اصلی سازمان خود را برای داشبورد مدیریتی ببینید.
۲. شروع کار
۲٫۱ آدرس پایه (Base URL)
تمام مسیرهای این سند نسبت به آدرس پایهی زیر در نظر گرفته شدهاند:
https://merchant.hamvest.com
۲٫۲ دریافت کلید API
برای فراخوانی هر Endpoint، سازمان شما به دو چیز نیاز دارد: یک نام کاربری سازمانی (username) و یک کلید API که بهعنوان توکن احراز هویت استفاده میشود. هر دو مقدار توسط تیم هموست در اختیار شما قرار میگیرند.
- کلید API یک رشتهی ۱۲۸ کاراکتری و یکتاست.
- این کلید معادل «رمز عبور» سازمان شماست؛ آن را در محیطی امن (مثل Secret Manager) نگه دارید و در کد منبع قرار ندهید.
- در صورت گم شدن کلید، باید از تیم هموست درخواست صدور کلید جدید کنید؛ کلید قبلی قابل بازیابی نیست.
۲٫۳ احراز هویت در درخواستها
هر درخواست به API باید دو هدر همزمان داشته باشد:
| هدر | مقدار | توضیح |
|---|---|---|
| X-Merchant | username سازمان شما | نام کاربری سازمان شما در سرویس هموست. |
| Authorization | Token API_KEY | کلید API با پیشوند ثابت «Token » و یک فاصله. مثلاً: Token 9f2a…c7d1 |
نمونهی کامل هدرهای یک درخواست:
X-Merchant: acme_123 Authorization: Token 9f2a....(128 character key)....c7d1 Content-Type: application/json
۲٫۴ فرمت دادهها
بدنهی همهی درخواستها و پاسخها در قالب JSON است. به نکات زیر توجه کنید:
- کلیدها همیشه انگلیسی و در قالب snake_case هستند.
- مقادیر اعشاری (مانند amount) معمولاً بهصورت رشته (string) برمیگردند تا از خطای دقت جلوگیری شود؛ سمت کلاینت آنها را به decimal مناسب تبدیل کنید.
- فیلد created_at بهصورت Unix timestamp (عدد صحیح به ثانیه) برمیگردد، نه رشتهی ISO 8601.
- قیمتها (price, buy_price, sell_price) برحسب واحد ریال برمیگردند.
۲٫۵ مستندات تعاملی Swagger
برای آزمایش سریع و تعاملی Endpointها، میتوانید از مستندات Swagger در مسیر /docs/ استفاده کنید. در این رابط میتوانید کلید API خود را وارد و درخواستها را بهصورت زنده اجرا کنید.
https://merchant.hamvest.com/docs/
۳. مفاهیم پایه
برای استفادهی صحیح از API، آشنایی با پنج مفهوم کلیدی زیر کفایت میکند.
۳٫۱ دارایی (Asset)
یک دارایی، یک قلم قابلمعامله است (مانند طلا، نقره، اوراق درآمد ثابت، سهام یا رمزارز). داراییهای قابل ارائه به سازمان شما توسط تیم هموست تعریف میشوند. هر دارایی این فیلدها را دارد:
| فیلد | توضیح |
|---|---|
| symbol | نماد یکتای دارایی، مثلاً GOLD18 یا USDT. |
| name | نام نمایشی دارایی. |
| buy_price | قیمت خرید سازمان از کاربر؛ در سفارش BUY استفاده میشود. |
| sell_price | قیمت فروش سازمان به کاربر؛ در سفارش SELL استفاده میشود. |
۳٫۲ کیفپول کاربر (User Wallet)
برای هر کاربر نهایی سازمان شما، یک «کیفپول کاربر» ساخته میشود. هر کیفپول یک شناسهی یکتای دلخواه (uuid) دارد که خودِ سازمان شما در زمان ساخت تعیین میکند (مثلاً همان شناسهی کاربر در سامانهی شما). تعداد کیفپولهای کاربری نامحدود است.
۳٫۳ کیفپول اصلی سازمان (Main Wallet)
سازمان شما یک «کیفپول اصلی» دارد که موجودی کل توکنهای در اختیار شما را نگه میدارد. این کیفپول از پیش توسط هموست ساخته میشود و نیاز به ایجاد آن نیست؛ شما فقط موجودی آن را میخوانید. در سفارشها، توکنها بین کیفپول کاربر و کیفپول اصلی جابهجا میشوند.
۳٫۴ موجودی دارایی و موجودی مسدودشده
در هر کیفپول، برای هر دارایی دو فیلد عددی نگهداری میشود:
| فیلد | توضیح |
|---|---|
| amount | موجودی کل دارایی در آن کیفپول. |
| blocked | بخش مسدودشده (رزروشده) از موجودی که قابل خرجکردن نیست. |
موجودی قابلاستفاده برای هر سفارش از رابطهی زیر محاسبه میشود:
available_balance = amount - blocked
۳٫۵ تراکنش (Transaction)
هر سفارش خرید یا فروش که با موفقیت ثبت شود، یک رکورد تراکنش میسازد. دو نوع تراکنش از سوی سازمان شما قابل ایجاد است:
| نوع | معنا |
|---|---|
| BUY (خرید سازمان) | سازمان از کاربر دارایی میخرد. توکن از کیفپول کاربر به کیفپول اصلی سازمان منتقل میشود. قیمت = buy_price. |
| SELL (فروش سازمان) | سازمان به کاربر دارایی میفروشد. توکن از کیفپول اصلی سازمان به کیفپول کاربر منتقل میشود. قیمت = sell_price. |
۴. جریان کاری معمول
یک جریان کامل از شروع یکپارچهسازی تا گزارشگیری روزانه، گامبهگام:
- ۱شروع کارنام کاربری و کلید API را از تیم هموست دریافت و در محیطی امن ذخیره کنید.
- ۲فهرست داراییهابا GET /api/v1/asset/ فهرست داراییها و قیمتهای لحظهای را بگیرید و به کاربران نشان دهید.
- ۳ساخت کیفپول کاربربرای هر کاربر جدید، یک کیفپول با uuid یکتا بسازید (POST /api/v1/wallet/). معمولاً همان شناسهی داخلی کاربر بهعنوان uuid استفاده میشود.
- ۴نمایش موجودی کاربرجزئیات کیفپول کاربر را با GET /api/v1/wallet/{id}/ بگیرید.
- ۵ثبت سفارش خرید/فروشبا POST /api/v1/order/ سفارش را ثبت کنید؛ در پاسخ موفق، جزئیات تراکنش (قیمت قطعی و مقدار توکن منتقلشده) برمیگردد.
- ۶گزارشگیری تراکنشهاتراکنشها را با GET /api/v1/transaction/ و فیلتر مناسب بخوانید.
- ۷نمایش موجودی سازماندر داشبورد مدیریتی، موجودی کیفپول اصلی سازمان را با GET /api/v1/wallet/main/ بخوانید.
۵. رفرنس کامل API
تمام مسیرها زیر /api/v1/ قرار دارند و همگی نیازمند دو هدر احراز هویت (بخش ۲٫۳) هستند.
۵٫۱ داراییها (Asset)
نمونهی پاسخ GET /api/v1/asset/:
GET /api/v1/asset/
[
{
"symbol": "GOLD18",
"name": "Gold 18K",
"buy_price": "4800000",
"sell_price": "5100000"
},
{
"symbol": "USDT",
"name": "Tether",
"buy_price": "84500",
"sell_price": "85200"
}
]پاسخ GET /api/v1/asset/{symbol}/ همان فیلدها را برای یک دارایی برمیگرداند. اگر نماد وجود نداشته باشد، کد 404 Not Found بازمیگردد.
۵٫۲ کیفپولها (Wallet)
۵٫۲٫۱ ساخت کیفپول کاربر
برای ساخت یک کیفپول کاربری، یک uuid یکتا (در سطح سازمان شما) ارسال کنید. تکراری بودن uuid با کد 409 Conflict رد میشود.
POST /api/v1/wallet/
{
"uuid": "user-7781"
}
// 201 Created
{
"id": 42,
"uuid": "user-7781",
"assets": []
}۵٫۲٫۲ فهرست کیفپولهای کاربری
پارامترهای Query پشتیبانیشده برای GET /api/v1/wallet/:
| پارامتر | توضیح |
|---|---|
| uuid | فیلتر بر اساس شناسهی یکتای کیفپول. |
| created_date_from / created_date_to | بازهی تاریخ ساخت (قالب YYYY-MM-DD یا ISO 8601). |
| updated_date_from / updated_date_to | بازهی تاریخ آخرین تغییر کیفپول. |
| ordering | مرتبسازی نتایج، مثلاً id- (نزولی) یا id (صعودی). |
| limit / offset | صفحهبندی؛ پیشفرض limit=10 و حداکثر ۱۰۰. |
۵٫۲٫۳ جزئیات کیفپول کاربر و کیفپول اصلی
پاسخ هر دو Endpoint شامل فهرست داراییهای موجود در کیفپول است. برای هر دارایی: نماد، مقدار، مقدار مسدودشده، قیمت خرید سازمان و ارزش ریالی معادل برمیگردد.
GET /api/v1/wallet/main/
[
{
"symbol": "GOLD18",
"amount": "200",
"blocked": "0",
"price": 4800000,
"value": "960000000"
}
]۵٫۳ سفارش خرید/فروش (Order)
فیلدهای ورودی:
| فیلد | الزام | توضیح |
|---|---|---|
| wallet_id | الزامی | شناسهی عددی کیفپول کاربر (از پاسخ ساخت کیفپول). |
| side | الزامی | نوع سفارش: BUY یا SELL (همیشه از دید سازمان شما). |
| asset | الزامی | نماد دارایی، مثلاً GOLD18. |
| amount | اختیاری | تعداد توکن دارایی (اعشاری). فقط اگر value ارسال نشود. |
| value | اختیاری | مبلغ ریالی سفارش (عدد صحیح). فقط اگر amount ارسال نشود. |
نمونهی درخواست و پاسخ یک سفارش فروش:
POST /api/v1/order/
{
"wallet_id": 42,
"side": "SELL",
"asset": "GOLD18",
"value": 5000000
}
// 201 Created
{
"id": 1903,
"wallet_id": 42,
"wallet_uuid": "user-7781",
"amount": "0.9803",
"price": 5100000,
"value": 5000000,
"asset": "GOLD18",
"transaction_type": "SELL",
"created_at": 1769000000
}۵٫۴ تراکنشها (Transaction)
این Endpoint تنها تراکنشهای نوع BUY و SELL را برمیگرداند. پارامترهای Query:
| پارامتر | توضیح |
|---|---|
| transaction_id | یافتن تراکنش با شناسهی دقیق؛ در صورت ارسال، سایر فیلترها نادیده گرفته میشوند. |
| transaction_type | نوع تراکنش: BUY یا SELL. |
| wallet_uuid / wallet_id | فیلتر بر اساس کیفپول کاربر (wallet_uuid در اولویت است). |
| date_from / date_to | بازهی زمانی ساخت تراکنش (YYYY-MM-DD یا ISO 8601). |
| ordering, limit, offset | مرتبسازی و صفحهبندی (پیشفرض limit=10، حداکثر ۱۰۰). |
فیلدهای پاسخ هر تراکنش:
| فیلد | توضیح |
|---|---|
| id | شناسهی یکتای تراکنش. |
| wallet_id / wallet_uuid | شناسهی کیفپول کاربر طرف تراکنش. |
| asset | نماد دارایی معاملهشده. |
| transaction_type | BUY یا SELL. |
| amount | تعداد توکن منتقلشده (رشته با دقت ۴ رقم اعشار). |
| price | قیمت قطعی هر واحد در زمان ثبت سفارش (عدد صحیح). |
| value | مبلغ ریالی تراکنش (عدد صحیح). |
| created_at | زمان ساخت تراکنش بهصورت Unix timestamp. |
۶. محاسبهی مقدار توکن و گرد کردن
چون قیمت داراییها لحظهای و عدد صحیح به ریال است، تبدیل بین «مبلغ ریالی» و «تعداد توکن» ممکن است باقیمانده داشته باشد. این بخش نحوهی این تبدیل را توضیح میدهد.
۶٫۱ تفاوت amount و value
| فیلد | نوع | معنا |
|---|---|---|
| amount | عدد اعشاری (تا ۴ رقم اعشار) | تعداد توکن دارایی، مثلاً «۲٫۰۰۰۰ گرم طلا». |
| value | عدد صحیح | مبلغ ریالی معادل. |
۶٫۲ جهت گرد کردن
سرویس همیشه با گام 0.0001 (چهار رقم اعشار) کار میکند. زمانی که value ارسال شود و سرویس باید amount را محاسبه کند، جهت گرد کردن به نوع سفارش بستگی دارد:
| نوع سفارش | جهت گرد کردن | توضیح |
|---|---|---|
| BUY (خرید سازمان) | به سمت بالا (ceil) | سازمان از کاربر میخرد؛ مقدار توکن گرفتهشده به سمت بالا گرد میشود. |
| SELL (فروش سازمان) | به سمت پایین (floor) | سازمان به کاربر میفروشد؛ مقدار توکن تحویلدادهشده به سمت پایین گرد میشود. |
در حالتی که amount خودِ سازمان ارسال شود، سرویس value را چنین محاسبه میکند:
value = int( amount * price )
۶٫۳ مثال عددی
مثال یک: سفارش فروش (SELL)
کاربر میخواهد به ارزش ۵٬۰۰۰٬۰۰۰ ریال طلا بخرد. سازمان سفارش SELL با value = 5,000,000 ثبت میکند. قیمت فروش = ۵٬۱۰۰٬۰۰۰ ریال.
amount = 5,000,000 / 5,100,000 = 0.98039... floor( .. , step=0.0001 ) -> amount = 0.9803 gram
نتیجه: ۰٫۹۸۰۳ گرم طلا از کیفپول اصلی سازمان به کیفپول کاربر منتقل میشود.
مثال دو: سفارش خرید (BUY) با amount
کاربر میخواهد ۲ گرم طلا به سازمان بفروشد. سازمان سفارش BUY با amount = 2 ثبت میکند. قیمت خرید = ۴٬۸۰۰٬۰۰۰ ریال.
value = int( 2 * 4,800,000 ) = 9,600,000 rial
نتیجه: ۲ گرم از کیفپول کاربر به کیفپول اصلی سازمان منتقل میشود و ۹٬۶۰۰٬۰۰۰ ریال در رکورد تراکنش بهعنوان value ثبت میگردد.
۷. مفهوم اضافهفروش در سفارش فروش
برای هر دارایی، تیم هموست بسته به مدل کسبوکار شما یک «سقف اضافهفروش» تنظیم میکند. اثر آن این است که در سفارشهای SELL، حتی اگر موجودی کیفپول اصلی سازمان کمی کمتر از مقدار مورد نیاز باشد، سفارش میتواند موفق ثبت شود و موجودی کیفپول اصلی بهصورت موقت منفی میشود.
- سقف اضافهفروش توسط هموست مدیریت میشود و سازمان شما نمیتواند آن را تغییر دهد.
- این رفتار فقط برای SELL اعمال میشود و در سفارشهای BUY تأثیری ندارد.
- منفی شدن موجودی کیفپول اصلی نشانهی خطا نیست؛ یعنی سازمان شما در محدودهی مجاز در حال «اضافهفروش» است و این موقعیت با عملیات بعدی متعادل میشود.
۸. کدهای پاسخ و پیامهای خطا
۸٫۱ کدهای پاسخ HTTP
| کد | معنا |
|---|---|
| 200 OK | فراخوانی GET با موفقیت انجام شد. |
| 201 Created | منبع جدید (کیفپول یا سفارش) با موفقیت ساخته شد. |
| 400 Bad Request | بدنه یا پارامترهای درخواست از نظر اعتبارسنجی نامعتبر است. |
| 401 Unauthorized | هدر احراز هویت ارسال نشده یا نامعتبر است. |
| 403 Forbidden | سازمان شما اجازهی این عملیات را ندارد یا غیرفعال شده است. |
| 404 Not Found | دارایی، کیفپول یا تراکنش مورد درخواست وجود ندارد. |
| 409 Conflict | تعارض داده؛ رایجترین مورد: uuid کیفپول تکراری است. |
۸٫۲ پیامهای خطای پرکاربرد
| پیام | علت و راهحل |
|---|---|
| Insufficient Balance | موجودی قابلاستفادهی کیفپول مبدأ کافی نیست. در BUY یعنی کیفپول کاربر و در SELL یعنی کیفپول اصلی (پس از در نظر گرفتن سقف اضافهفروش). |
| duplicate uuid | uuid کیفپول تکراری است (کد ۴۰۹). یک شناسهی یکتا بسازید. |
| Provide exactly one of amount or value | دقیقاً یکی از این دو فیلد را در بدنهی سفارش ارسال کنید. |
| Must be > 0 | مقدار amount یا value باید بزرگتر از صفر باشد. |
| Invalid Date Format | قالب تاریخِ ارسالی نامعتبر است؛ از YYYY-MM-DD یا ISO 8601 استفاده کنید. |
| Not Found (404) | نماد دارایی یا شناسهی کیفپول/تراکنش معتبر نیست؛ بررسی کنید دارایی متعلق به سازمان شما تعریف شده باشد. |
۹. سؤالات متداول
موجودی قابلاستفادهی کیفپول مبدأ کافی نبوده است. به یاد داشته باشید که بخش blocked از موجودی کنار گذاشته میشود و در سفارش فروش، تنها تا سقف اضافهفروشی که هموست تعیین کرده موجودی منفی مجاز است.
به دلیل گرد کردن با گام 0.0001. در BUY به سمت بالا و در SELL به سمت پایین گرد میشود. این اختلاف حداکثر در حد یک دههزارم از واحد دارایی است و مطابق طراحی سرویس است.
این حالت طبیعی است و به آن «اضافهفروش» میگویند: در سفارشهای فروش، کیفپول اصلی سازمان میتواند تا سقف تعیینشده توسط هموست بیش از موجودی واقعی خود بفروشد.
خیر. قیمتها بهصورت لحظهای توسط سامانهی قیمتگذاری هموست تعیین میشوند و در API فقط خواندنیاند. اسپرد بین قیمت خرید و فروش بخشی از مدل کسبوکار است و توسط هموست مدیریت میشود.
پیشنهاد میشود کیفپول هر کاربر در زمان عضویت/فعالسازی حساب در سامانهی شما ساخته شود تا در اولین معامله تأخیر اضافهای ایجاد نشود. میتوانید همان شناسهی داخلی کاربر را بهعنوان uuid ارسال کنید.
کلید API قابل بازیابی نیست. باید با تیم هموست تماس بگیرید تا یک کلید جدید برای سازمان شما صادر شود.
خیر. قیمتها لحظهای تغییر میکنند. پیشنهاد میشود قیمت را بلافاصله قبل از ثبت سفارش دوباره از API بگیرید تا کاربر قیمت بهروز را ببیند.
۱۰. واژهنامه
| اصطلاح | تعریف |
|---|---|
| سازمان شریک (Merchant) | سازمان مشتری سرویس که برای کاربران نهایی خود کیفپول و معامله مدیریت میکند؛ یعنی شما. |
| دارایی (Asset) | قلم قابلمعاملهی تعریفشده برای سازمان شما، با قیمتهای لحظهای خرید و فروش. |
| توکن (Token) | واحد دیجیتال نمایندهی دارایی که در کیفپولها نگهداری میشود؛ همان مقدار amount. |
| کیفپول کاربر (User Wallet) | کیفپول یک کاربر نهایی که سازمان شما برای او میسازد. |
| کیفپول اصلی (Main Wallet) | کیفپول مشترک سازمان شما؛ نگهدارندهی کل موجودی توکنهای در اختیار سازمان. |
| موجودی قابلاستفاده | amount منهای blocked؛ تنها این مقدار قابل خرجکردن است. |
| BUY (خرید سازمان) | سازمان شما از کاربر دارایی میخرد؛ قیمت = buy_price. |
| SELL (فروش سازمان) | سازمان شما به کاربر دارایی میفروشد؛ قیمت = sell_price. |
| اضافهفروش (Overdraft) | امکان فروش توسط کیفپول اصلی بیش از موجودی، تا سقفی که هموست تعیین میکند. |
| عملیات اتمیک (Atomic) | عملیاتی که یا کامل انجام میشود یا در صورت خطا هیچ اثری باقی نمیگذارد. |