پنل همکار → توسعهدهندگان → «دریافت کلید API». کلید به شکل smk_abcdefghij_plus48chars است و فقط یک بار نمایش داده میشود. اگر گمش کردید، کلید تازه صادر کنید: کلید قبلی بلافاصله از کار میافتد.
یک هدر اضافه کنید
Authorization: Bearer your_key.
دسترسی را بررسی کنید
موجودی را درخواست کنید. اگر پاسخ JSON با data برگشت، کلید پذیرفته شده است.
{
"data": [
{
"asset_id": "usdt", // همیشه usdt — موجودی دیگری وجود ندارد
"available_atomic": "15000000", // 15 USDT در واحد خرد (۶ رقم اعشار)
"available": "15", // همان مقدار به شکل اعشاری
"held_atomic": "0", // رزروشده برای برداشتهای تمامنشده
"held": "0"
}
]
}
اگر درخواست ناموفق بود
پاسخ
علت
401 unauthorized
کلید فرستاده نشده، فاصله دارد یا ناقص است. بعد از Bearer باید شناسه کامل smk_… بیاید.
401 key_inactive
کلید باطل شده است: کلید تازهای صادر شده، اما درخواست هنوز با کلید قبلی فرستاده میشود.
پنج قاعده
بیشتر خطاهای یکپارچهسازی از رعایتنکردن یکی از این قاعدهها میآید.
۱. مبلغها را بهصورت رشته بفرستید
یا amount را بفرستید — رشته اعشاری: "0.001"، "15" — یا amount_atomic را — عدد صحیح در واحد خرد: "100000" برای 0.001 BTC. دقیقاً یکی از این دو فیلد را بفرستید. پاسخها همیشه هر دو شکل را دارند: amount در کنار amount_atomic میآید.
نمونه
"amount": "0.001" // valid
"amount_atomic": "100000" // also valid
// both at once — 422
۲. asset_id را فقط از /assets بگیرید
کدهای مجاز: usdt، btc، xmr. مقدارهای دلخواه و شناسههای کاوشگرهای بلاکچین با خطای 422 رد میشوند.
شناسه یکتای هر تلاش. اگر اتصال قطع شد و نتیجه را نمیدانید، همان درخواست را با همان کلید تکرار کنید: نتیجه اصلی برمیگردد و عملیات دومی ساخته نمیشود. برای POST /invoices، POST /payments، POST /payouts/preview و POST /payouts الزامی است.
نمونه
Idempotency-Key: order-42-payment // first attempt → 201, created
Idempotency-Key: order-42-payment // retry → 200, same resource
Idempotency-Key: order-42-payment // different amount → 409 conflict
۴. فیلدهای خالی فرستاده نمیشوند
مقدارهای null و رشتههای خالی در پاسخ نمیآیند. پرداختی که هنوز انجام نشده، actual_amount، credited_amount و fee ندارد. وجود کلید را بررسی کنید، نه مقدار آن را.
expired به این معنی نیست که انتقال هرگز نمیرسد. آدرس حدود 6 ساعت دیگر هم پایش میشود و انتقالی که دیر برسد به موجودی واریز میشود. وضعیتهای نهایی همراه با واریز: confirmed، confirmed_underpaid، confirmed_overpaid.
سناریوها
هر سناریو چرخه کامل را نشان میدهد: ترتیب درخواستها، ساختار پاسخ و معنای فیلدها. توضیحهای داخل نمونههای JSON فقط برای فهم بهتر است و در پاسخهای واقعی وجود ندارد.
دریافت پرداخت
مشتری برای سفارش 60 USD با BTC پرداخت میکند
سفارش order-42. حدود 60 USDT لازم دارید؛ با قیمت حدود 60,000 برای BTC، مبلغی که از مشتری انتظار میرود 0.001 BTC است.
1
فهرست داراییهای موجود را بگیرید
پاسخ کد دارایی و decimals را برمیگرداند — تعداد رقمهای بعد از ممیز.
{
"data": [
{
"asset_id": "btc", // ← در درخواستهای بعدی از این استفاده کنید
"symbol": "BTC", // برای نمایش به کاربر
"network": "bitcoin", // در برداشتها استفاده میشود
"decimals": 8, // 1 BTC = 100000000 واحد خرد
"price_usd": "60000" // تقریبی، برای نرخ قطعی نیست
},
{
"asset_id": "usdt",
"symbol": "USDT",
"network": "TRON",
"decimals": 6,
"price_usd": "1.00"
}
]
}
2
نرخ را برای ۱۰ دقیقه قفل کنید
نرخ را تا وقتی مشتری در صفحه پرداخت است قفل میکند. در این مرحله نه پرداختی ساخته میشود نه آدرسی: فقط نرخ قطعی محاسبه میشود. پاسخ، مبلغی به USDT است که برای 0.001 BTC به موجودی واریز میشود.
مبلغ BTC مورد انتظار از مشتری. بهصورت رشته فرستاده میشود، نه عدد.
Idempotency-Key
اختیاری: عملیاتی ساخته نمیشود. میتوانید آن را بفرستید تا همان نرخ قطعی دوباره برگردد.
پاسخ
{
"data": {
"credit_lock_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
// ← برای مرحله بعد ذخیره کنید
"asset_id": "btc",
"expected_amount": "0.001", // مبلغی که از مشتری انتظار میرود
"expected_amount_atomic": "100000",
"credit_usdt": "59.4", // ← مبلغی که واریز میشود
"credit_usdt_atomic": "59400000",
"expires_at": "2026-08-11T17:20:00+00:00"
// ← پس از این زمان credit-preview نامعتبر است
}
}
expected_amount را به مشتری نشان دهید — یعنی چه مقدار BTC باید بفرستد.
3
پرداخت را بسازید و آدرس را بگیرید
این مرحله پرداخت را میسازد و آدرس واریز را برمیگرداند. مبلغ را در این درخواست نفرستید — در مرحله ۲ در credit-preview تعیین شده است.
به مشتری بگویید شبکه TRC20 است. اگر USDT در شبکه دیگری به این آدرس فرستاده شود، به موجودی واریز نمیشود.
مشتری کمتر از مبلغ خواستهشده فرستاد
انتظار 0.001 BTC بود و 0.0009 رسید — مثلاً کیف پول مشتری کارمزد شبکه را از خود مبلغ کم کرده است.
1
پرداخت را بررسی کنید
اگر کمتر از expected_amount رسیده ولی مبلغ هنوز برای واریز کافی است، وضعیت confirmed_underpaid میشود و credited_amount کمتر از مبلغ نرخ قطعی است. اگر مبلغ خیلی کم باشد، چیزی واریز نمیشود.
{
"data": {
"payment_id": "pay_01HZX...",
"status": "expired", // مهلت تمام شد
"asset_id": "btc",
"expected_amount": "0.001",
"deposit_address": "bc1qexampledepositaddress000000000",
"expires_at": "2026-08-11T18:00:00+00:00"
// actual_amount و credited_amount وجود ندارند — انتقالی نرسیده
}
}
2
مشتری دیر پرداخت کرد
اگر انتقال در بازه پایش اضافه برسد، پرداخت باز هم به confirmed میرود. سفارش را با expired حذف نکنید: آن را «دیرکرد» علامت بزنید و استعلام را ادامه دهید.
مبلغ سفارش بهصورت رشته. این endpoint فقط USD میپذیرد — نه amount_atomic.
fee_on
merchant — کارمزد را شما میپردازید و مشتری 15.00 میبیند. customer — کارمزد را مشتری میپردازد.
Idempotency-Key
الزامی. تکرار با همان کلید همان فاکتور را برمیگرداند.
partner_ref
اختیاری. Partner ID یکپارچهسازی که اتصال شما را راهاندازی کرده است (برنامه همکاری SnapEX Pay). حساب شما را یک بار به آن همکار متصل میکند؛ اگر خودتان یکپارچهسازی میکنید، آن را نفرستید.
کمپرداخت فاکتور را نمیبندد: وضعیت underpaid میشود و همان آدرس منتظر باقیمانده میماند (USDT — ۷۲ ساعت). اگر باقیمانده بهموقع نرسد، فاکتور با وضعیت partially_paid بسته میشود.
توجه
در رابط کاربری مشتری نام مسیرهای داخلی را نیاورید. صفحه پرداخت فقط آدرس، مبلغ و شبکه را نشان میدهد.
API بازپرداخت وجود ندارد. دومین انتقال کاملشده یک واریز جداگانه است، نه برگشت اولی.
برداشتها
انتقالهای خروجی از موجودی USDT شما.
برای مشتری 15 USDT را بهصورت BTC بفرستید
amount مبلغی است که از موجودی شما کسر میشود، نه مبلغی که گیرنده میگیرد. مبلغ گیرنده را preview برمیگرداند.
1
موجودی قابل برداشت را بررسی کنید
از available استفاده کنید، نه مجموع available و held. مبلغ held برای برداشتهای تمامنشده رزرو شده و قابل خرج نیست.
مبلغی به USDT که از موجودی شما کسر میشود. این مبلغ گیرنده نیست.
destination_asset_id
دارایی گیرنده. کد از GET /assets.
destination_network
شبکه گیرنده. برای BTC — bitcoin. آن را از network در GET /assets بگیرید.
destination_address
آدرس گیرنده. پیش از ارسال آن را بررسی کنید: انتقال قابل لغو نیست.
Idempotency-Key
الزامی. برای preview کلید جداگانه بگذارید.
پاسخ
{
"data": {
"preview_id": "c3d4e5f6-7890-abcd-ef12-34567890abcd",
// ← شناسه برای مرحله بعد
"from_asset_id": "usdt",
"from_amount": "15", // مبلغ کسر
"to_asset_id": "btc",
"to_amount": "0.000221", // ← مبلغی که گیرنده میگیرد
"fee_amount": "0.000019", // کارمزد به BTC، از قبل لحاظ شده
"expires_at": "2026-08-11T17:20:00+00:00"
// ← پیش از این زمان اجرا کنید
}
}
to_amount را به کاربر بهعنوان مبلغی که دریافت میکند نشان دهید. اگر مبلغ قابل قبول نیست، preview را اجرا نکنید: در زمان expires_at منقضی میشود.
3
برداشت را اجرا کنید
در این مرحله مبلغ کسر و ارسال میشود. آدرس و شبکه را در درخواست تکرار کنید — این کار جلوی جایگزینشدن آنها بین دو مرحله را میگیرد.
رد به دلیل منطق کسبوکار. ساختار پاسخ همان خطاهای اعتبارسنجی است.
details.amount
خطا به یک فیلد مربوط است و میتوان آن را کنار همان فیلد در فرم نشان داد.
پاسخ
{
"error": {
"code": "validation_error",
"message": "The request is invalid.",
"details": {
"amount": ["Insufficient balance."]
// ← علت رد به amount مربوط است
}
}
}
چیزی رزرو نمیشود. تکرار با همان Idempotency-Key بیخطر است؛ اول موجودی را شارژ کنید.
توجه
held را در نظر بگیرید: اگر بخشی از وجه برای برداشت دیگری رزرو شده باشد، available کمتر از انتظار شما خواهد بود.
عملیات
تاریخچه پرداختها
دفتر تراکنشها (ledger) فهرست عملیات است: واریزها، کسرها و رزروها بهصورت ردیفهای جداگانه ثبت میشوند.
1
تاریخچه را صفحه به صفحه بگیرید
ردیفها از جدیدترین به قدیمیترین برمیگردند. در هر درخواست حداکثر ۱۰۰ ردیف؛ صفحه بعد با cursor گرفته میشود.
{
"data": {
"payout_id": "payout_01HZX...", // ← همان شناسه پاسخ اول
"external_id": "wd-77",
"debit_amount": "15",
"status": "processing", // وضعیت ممکن است در این فاصله تغییر کرده باشد
"created_at": "2026-08-11T17:10:00+00:00"
}
}
HTTP 201 — عملیات در همین درخواست ساخته شد. HTTP 200 — از قبل وجود داشت. هر دو کد یعنی موفقیت.
2
اگر پارامترها عوض شده باشند
تکرار همان کلید با مبلغ یا آدرس دیگر رد میشود. این کار جلوی ناهمخوانی پارامترها را میگیرد.
تعارض: این کلید قبلاً به عملیات دیگری گره خورده است.
چه باید کرد
اگر برداشت تازهای است، Idempotency-Key تازه بگذارید.
پاسخ
{
"error": {
"code": "conflict",
"message": "Idempotency-Key was used with different parameters."
}
}
توجه
کلید را یک بار بسازید و همراه سفارش ذخیره کنید. اگر پیش از هر ارسال کلید تازه بسازید، محافظت در برابر تکرار از کار میافتد.
با HTTP 429، چند ثانیه بعد با همان کلید دوباره تلاش کنید.
وبهوکها
وقتی فاکتور، واریز، برداشت، تبدیل یا موجودی تغییر میکند، SnapEX یک درخواست POST به URL شما میفرستد. وبهوک فقط یک سیگنال است، نه مرجع نهایی: امضا را بررسی کنید و برای تصمیمهای مهم، شیء را دوباره از طریق API بخوانید.
راهاندازی
URL را در پنل تنظیم کنید
پنل همکار → توسعهدهندگان → کارت «Webhook»: URL را وارد کنید و «ذخیره» را بزنید. برای هر حساب یک URL؛ همه انواع رویداد جدول زیر به آن فرستاده میشوند.
رمز امضا را نگه دارید
در اولین ذخیره، پنل رمز whsec_… را فقط یک بار نشان میدهد. آن را فقط روی سرور خودتان نگه دارید. اگر بعداً URL را عوض کنید، رمز همان میماند.
شرایط URL
آدرس کامل https:// با میزبان عمومی: بدون login:password در URL، بدون localhost، و میزبان نباید به IP خصوصی یا رزروشده اشاره کند. URL هنگام ذخیره و دوباره پیش از هر تلاش تحویل بررسی میشود.
چه چیزی میرسد
هدر
معنی
Webhook-Id
شناسه یکتای رویداد (UUID)، برابر با id در بدنه. در تلاشهای دوباره و ارسال دستی تغییر نمیکند — تکراریها را با آن کنار بگذارید.
Webhook-Timestamp
زمان Unix به ثانیه، لحظه ارسال همین تلاش. هر تلاش دوباره مقدار تازه و امضای تازه دارد.
Webhook-Signature
v1= و پس از آن HMAC-SHA256 به hex با حروف کوچک از رشته «{Webhook-Timestamp}.{raw body}». کلید، کل رمز است، همراه با پیشوند whsec_.
Content-Type
همیشه application/json. بدنه JSON با کدگذاری UTF-8 است.
{
"id": "6f1c2a8e-3b4d-4f5a-9c7e-1a2b3c4d5e6f", // = Webhook-Id
"type": "invoice.paid", // نوع رویداد، جدول زیر را ببینید
"created_at": "2026-09-25T12:00:10+00:00", // زمان وقوع رویداد
"data": { // شیء در لحظه رویداد
"invoice_id": "INV-8K2M1Q0P",
"environment": "live",
"amount_usd": "15.00",
"charge_usd": "15.00",
"credit_usd": "13.85",
"status": "paid",
"external_id": "order-15",
"paid_at": "2026-09-25T12:00:10+00:00"
}
}
محتوای data به نوع رویداد بستگی دارد: invoice.* — فاکتور با همان ساختار GET /invoices/{id} (attempts خالی است و تلاش فعلی در payment است)؛ payment.* — واریز (payment_id، external_id، status، مبلغها)؛ payout.* — برداشت (payout_id، external_id، status، مبلغها)؛ conversion.* — تبدیل (conversion_id، status، مبلغها)؛ balance.changed — asset_id، entry_type، available_atomic و held_atomic پس از تغییر.
انواع رویداد
رویداد
معنی
invoice.created
فاکتور ساخته شد؛ روش پرداخت هنوز انتخاب نشده است (open).
invoice.awaiting
روش پرداخت انتخاب و آدرس صادر شد (awaiting).
invoice.underpaid
بخشی از مبلغ رسید؛ همان آدرس منتظر باقیمانده است (underpaid).
invoice.paid
کل مبلغ پرداخت و واریز شد (paid، نهایی). تنها سیگنال برای ارسال سفارش.
invoice.partially_paid
مشتری فقط بخشی از مبلغ را پرداخت کرد، مهلت تکمیل تمام شد و بخش دریافتشده به موجودی شما واریز شد (partially_paid، نهایی).
invoice.expired
مهلت فاکتور بدون پرداخت تمام شد (expired، نهایی).
invoice.extra_payment
پس از پرداخت فاکتور، انتقال دیگری رسید؛ جداگانه واریز میشود.
payment.created
یک واریز ساخته شد.
payment.detected
انتقال در شبکه دیده شد اما هنوز به موجودی واریز نشده است.
payment.credited
واریز به موجودی نشست (یکی از وضعیتهای confirmed*).
payment.expired
مهلت واریز تمام شد.
payout.created
برداشت ساخته و وجه آن رزرو شد.
payout.processing
برداشت در حال ارسال است.
payout.completed
وجه به گیرنده رسید.
payout.failed
برداشت ناموفق بود.
conversion.completed
تبدیل انجام شد.
conversion.failed
تبدیل بهطور کامل یا جزئی ناموفق بود.
balance.changed
یک ردیف موجودی ثبت شد: واریز، رزرو یا کسر.
سفارش را فقط با invoice.paid ارسال کنید — این رویداد فقط وقتی فرستاده میشود که کل مبلغ پرداخت شده باشد. invoice.underpaid و invoice.partially_paid یعنی مبلغ کامل نیست.
فاکتورهایی که با environment=test ساخته میشوند شبیهسازی هستند: همان وضعیتها را طی میکنند و همان وبهوکها را میفرستند (data.environment = "test")، اما هرگز موجودی واقعی را تغییر نمیدهند.
تحویل و تلاش دوباره
هر پاسخ 2xx موفق است. هر کد دیگر، پایان مهلت یا خطای شبکه ناموفق حساب میشود. بدنه پاسخ بررسی نمیشود.
مهلتها: ۵ ثانیه برای اتصال، ۱۵ ثانیه برای کل درخواست.
ریدایرکت دنبال نمیشود: 301/302 ناموفق حساب میشود. URL نهایی را وارد کنید.
حداکثر ۵ تلاش برای هر رویداد: تلاش اول و سپس تلاشهای دوباره حدود ۱۰ ثانیه، ۱ دقیقه، ۵ دقیقه و ۱۵ دقیقه پس از هر شکست. پس از پنجمین شکست، تحویل خودکار متوقف میشود.
کارت «ارسالهای وبهوک» در همین صفحه رویداد، کد HTTP یا خطا، زمان و شماره تلاش را نشان میدهد. دکمه «ارسال دوباره» رویداد را دوباره با همان Webhook-Id میفرستد.
تحویل «دستکم یک بار» است: یک رویداد ممکن است چند بار برسد و رویدادها ممکن است بیترتیب برسند (تلاش دوباره یک رویداد ممکن است بعد از رویداد جدیدتر برسد).
بررسی امضا
بدنه خام درخواست را بهصورت بایت و پیش از پارسکردن JSON بخوانید. JSONی که دوباره سریالسازی شود با امضا مطابقت نخواهد داشت.
HMAC-SHA256 را روی «{Webhook-Timestamp}.{raw body}» با رمز whsec_… خود بهعنوان کلید محاسبه و به hex تبدیل کنید.
«v1=» + hex را با هدر Webhook-Signature با یک تابع زمانثابت مقایسه کنید: hash_equals، crypto.timingSafeEqual، hmac.compare_digest.
Webhook-Timestamp را که بیش از ۵ دقیقه با ساعت شما اختلاف دارد رد کنید (توصیهشده). تلاشهای دوباره زمان تازه دارند، پس این کار آنها را خراب نمیکند.
PHP
<?php
$secret = getenv('SNAPEX_WEBHOOK_SECRET'); // whsec_… از پنل
$body = file_get_contents('php://input'); // بدنه خام، پیش از پارس JSON
$timestamp = $_SERVER['HTTP_WEBHOOK_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_WEBHOOK_SIGNATURE'] ?? '';
$expected = 'v1='.hash_hmac('sha256', $timestamp.'.'.$body, $secret);
if (! ctype_digit($timestamp)
|| abs(time() - (int) $timestamp) > 300
|| ! hash_equals($expected, $signature)) {
http_response_code(400);
exit;
}
$event = json_decode($body, true);
// اگر این Webhook-Id قبلاً پردازش شده، از آن بگذرید؛ کار سنگین را در صف انجام دهید
http_response_code(200);
Node.js
const crypto = require('crypto');
const express = require('express');
const app = express();
const secret = process.env.SNAPEX_WEBHOOK_SECRET; // whsec_… از پنل
// بدنه خام، پیش از پارس JSON
app.post('/hooks/snapex', express.raw({ type: 'application/json' }), (req, res) => {
const timestamp = req.get('Webhook-Timestamp') || '';
const signature = Buffer.from(req.get('Webhook-Signature') || '');
const expected = Buffer.from('v1=' + crypto.createHmac('sha256', secret)
.update(timestamp + '.').update(req.body).digest('hex'));
const ok = /^\d+$/.test(timestamp)
&& Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300
&& signature.length === expected.length
&& crypto.timingSafeEqual(signature, expected);
if (!ok) return res.sendStatus(400);
const event = JSON.parse(req.body.toString('utf8'));
// اگر این Webhook-Id قبلاً پردازش شده، از آن بگذرید؛ کار سنگین را در صف انجام دهید
res.sendStatus(200);
});
Python
import hashlib, hmac, os, time
from flask import Flask, abort, request
app = Flask(__name__)
SECRET = os.environ["SNAPEX_WEBHOOK_SECRET"].encode() # whsec_… از پنل
@app.post("/hooks/snapex")
def snapex_webhook():
body = request.get_data() # بدنه خام، پیش از پارس JSON
timestamp = request.headers.get("Webhook-Timestamp", "")
signature = request.headers.get("Webhook-Signature", "")
expected = "v1=" + hmac.new(SECRET, timestamp.encode() + b"." + body, hashlib.sha256).hexdigest()
if not (timestamp.isascii() and timestamp.isdigit()) \
or abs(time.time() - int(timestamp)) > 300 \
or not hmac.compare_digest(expected.encode(), signature.encode()):
abort(400)
event = request.get_json()
# اگر این Webhook-Id قبلاً پردازش شده، از آن بگذرید؛ کار سنگین را در صف انجام دهید
return "", 200
چکلیست هندلر
امضا را روی بدنه خام و با مقایسه زمانثابت بررسی کنید؛ اگر مطابقت نداشت، 400 برگردانید.
درخواستهایی را که Webhook-Timestamp آنها قدیمیتر از ۵ دقیقه است رد کنید.
مقدارهای Webhook-Id پردازششده را ذخیره کنید و تکراریها را نادیده بگیرید. به ترتیب رسیدن تکیه نکنید: وضعیت داخل رویداد را با آنچه از قبل دارید مقایسه کنید.
سریع 2xx برگردانید، خیلی زودتر از ۱۵ ثانیه، و کار سنگین را ناهمگام انجام دهید.
پس از وبهوک میتوانید برای اطمینان، شیء را دوباره از طریق API بخوانید: GET /invoices/{id}، GET /payments/{id}، GET /payouts/{id}.
وضعیتها
نشان «نهایی» یعنی وضعیت دیگر تغییر نمیکند. تنها استثنا واریزهای منقضیشده است: انتقالی که دیر برسد هنوز ممکن است دریافت شود.
واریزها
وضعیت
معنی
چه باید کرد
awaiting_deposit
آدرس صادر شد، در انتظار انتقال
آدرس و مبلغ را به مشتری نشان دهید
detected
انتقال در شبکه دیده شد، هنوز واریز نشده
صبر کنید. سفارش را نبندید
processing
در حال تبدیل به USDT
صبر کنید
confirmed
مبلغ مورد انتظار رسید، وجه واریز شد
سفارش را ببندید
نهایی
confirmed_underpaid
کمتر از مبلغ مورد انتظار رسید، در محدوده مجاز
credited_amount را بررسی کنید و تصمیم بگیرید که کافی است یا نه
نهایی
confirmed_overpaid
بیشتر از مبلغ مورد انتظار رسید، طبق credit-preview واریز شد
سفارش را ببندید. درباره مبلغ اضافه با پشتیبانی تماس بگیرید
نهایی
confirmed_mismatch
برای سازگاری با نسخههای قبلی نگه داشته شده
برای پرداختهای جدید استفاده نمیشود
نهایی
manual_review
نیاز به بررسی دستی
منتظر بررسی بمانید؛ پرداخت دوم نسازید
expired
مهلت پرداخت تمام شد، آدرس تا حدود 6 ساعت دیگر پایش میشود
سفارش را حذف نکنید؛ استعلام را ادامه دهید
failed
خطا در سمت ارائهدهنده
پرداخت تازه بسازید
نهایی
cancelled
پرداخت لغو شد
پرداخت تازه بسازید
نهایی
refunded
ارائهدهنده وجه را برگرداند
موجودی را تطبیق دهید؛ اگر مطابقت نداشت، با پشتیبانی تماس بگیرید
نهایی
فاکتورها
وضعیت
معنی
چه باید کرد
open
فاکتور ساخته شد، روش پرداخت انتخاب نشده
pay_url را به مشتری بدهید یا asset_id را خودتان انتخاب کنید
awaiting
آدرس صادر شد، در انتظار انتقال
آدرس و مبلغ را نشان دهید؛ وضعیت را استعلام کنید
underpaid
بخشی از مبلغ رسید؛ همان آدرس
از مشتری بخواهید باقیمانده را به همین آدرس بفرستد
paid
اولین انتقال کامل واریز شد
سفارش را ببندید
نهایی
partially_paid
مشتری فقط بخشی از مبلغ را پرداخت کرد، مهلت تکمیل تمام شد و بخش دریافتشده به موجودی شما واریز شد
سفارش را بهعنوان پرداختشده ارسال نکنید؛ باقیمانده را با مشتری تسویه کنید
نهایی
expired
مهلت فاکتور تمام شد
فاکتور تازه بسازید
نهایی
برداشتها
وضعیت
معنی
چه باید کرد
reserved
وجه برای برداشت رزرو شد
صبر کنید
submitting
به ارائهدهنده فرستاده شد
صبر کنید
processing
ارائهدهنده در حال ارسال در بلاکچین است
صبر کنید
completed
وجه به گیرنده رسید
انجام شد
نهایی
manual_review
نتیجه مشخص نیست
برداشت دیگری نسازید؛ منتظر بررسی بمانید
failed
انتقال ناموفق بود؛ مبلغ رزروشده معمولاً آزاد میشود
موجودی را بررسی کنید؛ در صورت نیاز با Idempotency-Key تازه دوباره تلاش کنید
نهایی
خطاها
پاسخ موفق همیشه در data است و خطا همیشه در error. قالب دیگری برای پاسخ وجود ندارد.
ساختار خطا
{
"error": {
"code": "validation_error", // کد قابلپردازش برای برنامه، جدول زیر را ببینید
"message": "The request is invalid.",
"details": { // همیشه وجود ندارد
"destination_address": ["The destination address field is required."]
// کلید، نام فیلدی است که اعتبارسنجی آن رد شد
}
}
}
HTTP
code
چه زمانی
چه باید کرد
401
unauthorized
کلید فرستاده نشده یا نامعتبر است
هدر Authorization: Bearer smk_… را کامل و بدون فاصله یا شکست خط بررسی کنید
401
key_inactive
کلید باطل شده است
کلید قبلی باطل شده است. کلید فعلی را از پنل بگیرید
401
key_expired
کلید منقضی شده است
کلید تازه صادر کنید
404
not_found
شناسه پیدا نشد یا متعلق به فروشنده دیگری است
از payment_id یا payout_id پاسخهای خودتان استفاده کنید
409
conflict
Idempotency-Key به عملیات دیگری گره خورده است، یا external_id قبلاً استفاده شده است
برای عملیات تازه کلید تازه بگذارید. برای تکرار، همان کلید و همان پارامترها را بفرستید
422
validation_error
فیلدهای نامعتبر، credit-preview منقضیشده، موجودی ناکافی یا نبود Idempotency-Key
فیلد و علت را در details ببینید
429
rate_limited
از سقف تعداد درخواست بیشتر شد
بعداً با همان Idempotency-Key دوباره تلاش کنید
500
internal_error
خطای داخلی سرور
بعداً با همان Idempotency-Key دوباره تلاش کنید. اگر ادامه داشت، با پشتیبانی تماس بگیرید و X-Request-Id را بفرستید