شروع سریع
آدرس پایه همه درخواستها:
https://gateway.bazaar-pay.ir- ثبتنام کنید و سرویسهای مورد نیاز را درخواست دهید.
- پس از تأیید حساب، در پنل › کلیدهای API یک کلید بسازید. رمز کلید (secretKey) فقط یکبار نمایش داده میشود.
- با کلید، توکن دسترسی بگیرید و آن را در هدر
Authorizationبفرستید. - مسیرها و بدنه درخواستها را مطابق مرجع API فراخوانی کنید.
احراز هویت و توکن
یک جفت کلید apiKey / secretKey برای همه محصولات کار میکند. برای سازگاری با کلاینتهای موجود، هر محصول همان مسیر و قالب توکن خودش را دارد و توکن صادرشده از هر کدام برای همه محصولات معتبر است (احراز هویت بایومتریک alpha مسیر توکن ندارد و از همین توکنها استفاده میکند).
توجه به نام فیلدها: بدنه دریافت توکن در ide و mzahub فیلدهای apiKey / secretKey (camelCase) و در پیامک pulse فیلدهای api_key / secret_key (snake_case) دارد؛ پاسخها هم به همین ترتیباند. این تفاوت عمدی و برای سازگاری با کلاینتهای موجود هر محصول است.
- اعتبار توکن دسترسی: ۲۴ ساعت — اعتبار توکن تازهسازی: ۴۸ ساعت.
- توکن را در هدر
Authorization: Bearer <accessToken>ارسال کنید. - پیش از انقضا با توکن تازهسازی، جفت توکن جدید بگیرید.
استعلام (ide)
POST /ide/v1/tokens/generate{"apiKey": "…", "secretKey": "…"}{"accessToken": "…", "refreshToken": "…"}POST /ide/v1/tokens/refresh{"refreshToken": "…"}پاسخ: همان قالب دریافت توکن.
پیامک (pulse)
POST /pulse/api/v1/auth/authenticate{"api_key": "…", "secret_key": "…"}{"access_token": "…", "refresh_token": "…"}POST /pulse/api/v1/auth/refresh-token{"access_token": "…", "refresh_token": "…"}پاسخ: همان قالب دریافت توکن.
قرارداد و امضا (mzahub)
POST /mzahub/v1/auth/login{"apiKey": "…", "secretKey": "…"}{"accessToken": "…", "refreshToken": "…", "expiresIn": 86400, "refreshTokenExpiresIn": 172800, "tokenType": "Bearer"}POST /mzahub/v1/auth/refresh{"refreshToken": "…"}پاسخ: همان قالب دریافت توکن.
هدرهای درخواست
| هدر | الزام | توضیح |
|---|---|---|
Authorization | الزامی | Bearer <accessToken> |
X-TRACK-ID | اختیاری | شناسه پیگیری دلخواه شما؛ در گزارش مصرف پنل ذخیره و قابل جستوجو است. |
X-REAL-IP | اختیاری | در API اصلی قرارداد دیجیتال الزامی است، اما برای مسیرهای /mzahub درگاه لازم نیست؛ درگاه IP ثبتشدهی سرور خودش را بهجای آن ارسال میکند. |
Content-Type | شرطی | فقط درخواستهای بدنهدار (POST): application/json یا multipart/form-data مطابق هر سرویس. |
محدودیت IP
برای هر کلید API میتوانید فهرست IPهای مجاز تعریف کنید. در این صورت هم دریافت توکن و هم فراخوانی سرویسها فقط از همین IPها پذیرفته میشود و در غیر این صورت خطای forbidden.ip برمیگردد. فهرست خالی یعنی همه IPها مجازند — برای محیط عملیاتی حتماً IP سرورهای خود را ثبت کنید.
کلید تست (sandbox)
هنگام ساخت کلید در پنل میتوانید آن را «کلید تست» علامت بزنید (پیشوند bp_test_). درخواستهای این کلید همان بررسیهای کلید عادی را دارند (حساب فعال، دسترسی سرویس، IP، سقف نرخ و مالکیت منابع) اما به ارائهدهنده ارسال نمیشوند: پاسخ نمونهای با همان ساختار مرجع API برمیگردد، هیچ هزینهای کسر نمیشود و در گزارش مصرف با برچسب «تست» دیده میشوند (در آمار، صورتحساب و وضعیت سرویسها حساب نمیشوند).
برای آزمودن مسیر خطا، هدر X-Mock-Status: 503 یا پارامتر کوئری ?X-Mock-Status=503 را با کلید تست بفرستید تا همان کد وضعیت برگردد.
نمونه کد
TOKEN=$(curl -s -X POST https://gateway.bazaar-pay.ir/ide/v1/tokens/generate \
-H "Content-Type: application/json" \
-d '{"apiKey":"YOUR_API_KEY","secretKey":"YOUR_SECRET_KEY"}' | jq -r .accessToken)
curl "https://gateway.bazaar-pay.ir/ide/v1/services/matching?nationalCode=0012345678&mobileNumber=09120000000" \
-H "Authorization: Bearer $TOKEN" \
-H "X-TRACK-ID: order-1001"هزینه و صورتحساب
- هر سرویس قیمت مشخصی (به ریال) دارد که در کاتالوگ و پنل نمایش داده میشود؛ ممکن است قیمت اختصاصی برای حساب شما تعریف شده باشد.
- برخی درخواستها چند سرویس را همزمان مصرف میکنند؛ مثلاً استعلام شخص حقوقی همراه با پارامتر
ceo=trueهر دو سرویس را محاسبه میکند. - درخواستهای موفق (کد وضعیت کمتر از ۴۰۰) محاسبه میشوند. خطاهای سمت ارائهدهنده (
5xx) و قطعی ارتباط هرگز محاسبه نمیشوند. برای برخی سرویسها پاسخهای4xx(به جز ۴۰۱، ۴۰۳ و ۴۲۹) طبق قوانین ارائهدهنده محاسبه میشود. - مبلغ پیش از ارسال درخواست رزرو و پس از دریافت پاسخ تسویه میشود؛ اگر اعتبار کافی نباشد خطای
credit.insufficient(کد ۴۰۲) برمیگردد. - پیشپرداخت: مصرف از موجودی کیف پول کسر میشود. پسپرداخت: تا سقف اعتبار توافقی مصرف میکنید و ابتدای هر ماه صورتحساب ماه قبل صادر میشود.
محاسبه پیامک
هزینه پیامک به ازای هر بخش (segment) و هر گیرنده محاسبه میشود. پیامک فارسی تا ۷۰ نویسه یک بخش است (در پیامک چندبخشی هر بخش ۶۷ نویسه) و پیامک لاتین تا ۱۶۰ نویسه (چندبخشی ۱۵۳). مبنای نهایی، مقدار segment_count در پاسخ ارائهدهنده است.
مالکیت منابع
پیامکها و قراردادهایی که از طریق حساب شما ایجاد میشوند به حساب شما تعلق دارند. استعلام وضعیت پیامک، استعلام/لغو/دانلود قرارداد و مراحل امضا فقط برای منابع متعلق به خود شما پاسخ داده میشود و برای سایر شناسهها خطای service.not_found برمیگردد.
محدودیت نرخ و صف
هر حساب سقف تعداد درخواست در ثانیه دارد (مقدار آن در پنل نمایش داده میشود). درخواستی که از سقف بگذرد فوراً رد نمیشود؛ در صف میماند تا نوبتش برسد، حداکثر به اندازه «زمان انتظار مجاز» حساب (پیشفرض ۳ ثانیه). اگر در این مدت نوبت نرسد، خطای ۴۲۹ با هدر Retry-After برمیگردد و هزینهای کسر نمیشود.
زمان پاسخ همیشه محدود است: زمان انتظار در صف + مهلت سرویسدهنده. مهلت استعلام و پیامک ۱۵ ثانیه و قرارداد و احراز هویت ویدیویی ۱۰۰ ثانیه است؛ پس از آن خطای ۵۰۴ upstream.timeout برمیگردد. مدت انتظار هر درخواست در هدر پاسخ X-Queue-Time (میلیثانیه) میآید.
درخواست دستهای (ناهمزمان)
برای فهرستهای بزرگ (مثلاً ۱۰ هزار استعلام) همه درخواستها را یکجا ثبت کنید و نتیجه را بعداً بگیرید. هر آیتم دقیقاً مثل یک فراخوانی مستقیم اجرا و محاسبه میشود (همان مسیر، بدنه، دسترسی و قیمت) و با شناسه پیگیری batch-<id>-<seq> در گزارش مصرف دیده میشود.
- حداکثر ۱۰٬۰۰۰ آیتم و ۲ مگابایت در هر درخواست؛ احراز هویت با همان توکن دسترسی.
deadlineMinutes(پیشفرض ۳۰، حداکثر ۱۴۴۰): آیتمهایی که تا این مهلت اجرا نشوند منقضی میشوند و هزینهای ندارند.- خطاهای موقت (۴۲۹، ۵۰۲، ۵۰۳، ۵۰۴) خودکار دوباره تلاش میشوند؛ پاسخهای دیگر همانطور که هستند ذخیره میشوند.
callbackUrl(اختیاری، فقط https): پس از پایان دسته، خلاصه وضعیت به این آدرس POST میشود. نتیجهها در آن نیست؛ آنها را با توکن خودتان از API بگیرید.- نتیجهها ۳۰ روز نگه داشته میشوند.
POST /api/v1/batches
Authorization: Bearer <accessToken>
Content-Type: application/json
{
"items": [
{"method": "GET", "path": "/ide/v1/cards?number=6037990000000000"},
{"method": "POST", "path": "/pulse/api/v1/message/sms/send", "body": {"receptor": "0912…", "message": "…", "sender": "3000…"}}
],
"deadlineMinutes": 30,
"callbackUrl": "https://example.com/hooks/batch"
}
→ 202 {"batchId": 42, "status": "running", "total": 2, "deadline": "…"}
GET /api/v1/batches/42
→ {"batchId": 42, "status": "done", "total": 2, "pending": 0, "running": 0, "done": 2, "succeeded": 2, "expired": 0, …}
GET /api/v1/batches/42/items?after=-1&limit=500
→ {"items": [{"seq": 0, "status": "done", "httpStatus": 200, "response": {…}}, …]}وبهوک
در پنل › وبهوکها آدرسهای https خود را ثبت و رویدادها را انتخاب کنید. آدرسهای داخلی، loopback و IPهای خصوصی پذیرفته نمیشوند.
| رویداد | زمان ارسال | data |
|---|---|---|
batch.completed | پایان یک درخواست دستهای | {batchId, status, total} |
sms.mo.received | دریافت پیامک روی خطوط اختصاصی شما (حدود یک دقیقه تأخیر؛ پس از قطعی تا ۲۴ ساعت، پیامکهای جامانده هم ارسال میشوند) | {id, sender, receptor, message, received_date_time} |
webhook.test | دکمه «ارسال آزمایشی» در پنل | {message} |
وضعیت تحویل پیامک و وضعیت قرارداد از سمت ارائهدهنده اعلام نمیشود و رویداد ندارد؛ آنها را مانند قبل استعلام کنید.
- بدنه:
{"id", "type", "createdAt", "data"}با هدرهایX-Webhook-Id(شناسه رویداد، در تلاشهای مجدد ثابت)،X-Webhook-Event،X-Webhook-Timestamp(ثانیه یونیکس) وX-Webhook-Signature. - امضا:
v1=hex(HMAC-SHA256(secret, timestamp + "." + body)). امضا را با بدنه خام بررسی کنید و رویدادهای قدیمیتر از چند دقیقه را رد کنید. رمز در پنل فقط یک بار نمایش داده میشود و با «رمز جدید» عوض میشود؛ از همان لحظه همه ارسالها با رمز جدید امضا میشوند. - هر پاسخ
2xxیعنی تحویل. در غیر این صورت پس از ۳۰ ثانیه، ۲، ۸ و ۳۲ دقیقه، حدود ۲ و ۸٫۵ ساعت و ۱۲ ساعت دوباره ارسال میشود (۸ تلاش) و سپس «ناموفق» ثبت میشود. سابقه ارسال ۳۰ روز در پنل میماند.
کدهای خطا
پاسخهای ارائهدهنده بدون تغییر برگردانده میشوند. خطاهای خود درگاه با قالب همان محصول برمیگردند:
// ide, pulse, mzahub
{"code": "credit.insufficient", "message": "…"}
// alpha
{"errorCode": "credit.insufficient", "errorMessage": "…", "data": null}| HTTP | کد | توضیح |
|---|---|---|
| ۴۰۱ | unauthorized | توکن ارسال نشده، نامعتبر یا منقضی شده است. |
| ۴۰۲ | credit.insufficient | اعتبار کیف پول (یا سقف اعتبار پسپرداخت) کافی نیست. |
| ۴۰۲ | spend.limit | سقف هزینه ماهانه این کلید API در ماه شمسی جاری پر شده است. |
| ۴۰۳ | forbidden.scope | این کلید API به محصول یا سرویس درخواستی دسترسی ندارد (دامنه دسترسی کلید). |
| ۴۰۳ | forbidden.ip | درخواست از IP خارج از فهرست مجاز کلید ارسال شده است. |
| ۴۰۳ | forbidden.service | این سرویس برای حساب شما فعال نشده است؛ از پنل درخواست دهید. |
| ۴۰۳ | customer.inactive | حساب شما هنوز تأیید نشده یا معلق است. |
| ۴۰۴ | service.not_found | مسیر یا سرویس وجود ندارد، یا منبع (پیامک/قرارداد) متعلق به شما نیست. |
| ۴۲۹ | rate.limited | در زمان انتظار مجاز، نوبت سقف نرخ حساب به درخواست نرسید (هدر Retry-After). |
| ۴۲۹ | queue.timeout | صف سرویسدهنده در زمان انتظار مجاز خالی نشد؛ هزینهای کسر نمیشود (هدر Retry-After). |
| ۵۰۲ | upstream.unavailable | ارائهدهنده سرویس در دسترس نیست؛ هزینهای کسر نمیشود. |
| ۵۰۴ | upstream.timeout | ارائهدهنده در زمان مقرر پاسخ نداد؛ هزینهای کسر نمیشود. |
وضعیت سرویسها
وضعیت لحظهای هر سرویس بدون نیاز به توکن از GET /api/v1/public/status در دسترس است و هر ۳۰ ثانیه بهروز میشود. وضعیت از درخواستهای واقعی یک ساعت اخیر محاسبه میشود و برای هر سرویس دسترسپذیری ۲۴ ساعت، تأخیر p95 و دسترسپذیری هر ساعت (۲۴ مقدار، قدیمیترین اول؛ null یعنی بدون ترافیک) برمیگردد.
همین اطلاعات در صفحه وضعیت سرویسها نمایش داده میشود.
مقادیر status: operational (عملیاتی)، degraded (کاهش کیفیت)، down (قطع)، unknown (بدون ترافیک در یک ساعت اخیر). پیش از تلاش مجدد خودکار در خطای upstream.unavailable میتوانید این مسیر را بررسی کنید.
مرجع کامل API
جزئیات همه مسیرها، پارامترها و پاسخها را در مرجع تعاملی ببینید. فایل OpenAPI نیز برای تولید خودکار کلاینت و مجموعه Postman برای آزمودن سریع در دسترس است.
در Postman متغیرهای apiKey و secretKey را پر کنید و درخواست دریافت توکن را بفرستید؛ توکن در accessToken ذخیره و برای بقیه درخواستها استفاده میشود. مشخصات API پنل (ورود، کلیدها، مصرف، وبهوک و درخواست دستهای) در /api/v1/public/control-openapi.json است.