API نسخهٔ ۱ — پایدار

مرجع API نمایندگی دامنه

یک رابطِ HTTP برای ثبت، تمدید و مدیریت دامنه با قیمتِ سطحِ نمایندگی شما — طراحی‌شده برای فراخوانیِ خودکار از سامانهٔ صورت‌حسابِ خودتان. ماژول‌های آمادهٔ WHMCS و ووکامرس روی همین رابط ساخته شده‌اند.

https://servernet.cloud/developers · ۱۴۰۵/۰۶/۰۳

دنبال مدیریت کاربران تونل سرور اکسیت هستید؟ آن رابط مرجع خودش را دارد: مرجع API تونل سرور اکسیت

۱آغاز به کار

  1. حسابِ شما باید به‌عنوان نمایندهٔ دامنه فعال شده باشد. تا پیش از آن، نقاطِ پایانیِ دامنه پاسخِ مجازنبودن می‌دهند.
  2. در پنل کاربری، بخش امنیت، یک توکن API صادر کنید و دامنهٔ دسترسیِ آن را به کمترین چیزی که یکپارچه‌سازی‌تان لازم دارد محدود کنید.
  3. نشانی IP خروجیِ سرورِ خودتان را در فهرستِ مجازِ همان توکن ثبت کنید. توکنِ بدونِ محدودیتِ IP از هر نقطه‌ای قابلِ استفاده است.
  4. حساب را شارژ کنید. ثبت و تمدید در لحظهٔ فراخوانی از اعتبار تسویه می‌شوند و صورت‌حسابِ پس از مصرف وجود ندارد.
  5. فراخوانیِ آزمایشی به نقطهٔ پایانیِ سلامت بزنید و سطح و اعتبارِ برگشتی را با پنل مقایسه کنید.
متنِ خامِ توکن تنها یک بار، در لحظهٔ صدور، نمایش داده می‌شود. ما فقط چکیدهٔ رمزنگاریِ آن را نگه می‌داریم و بازیابی‌اش از نظرِ محاسباتی ممکن نیست. توکنِ گم‌شده را باید باطل و توکنِ تازه صادر کرد؛ ابطال آنی است و بر توکن‌های دیگرِ همان حساب اثری ندارد.

۲احراز هویت و دامنهٔ دسترسی

احراز هویت با توکنِ حامل در هدرِ Authorization انجام می‌شود. نشست، کوکی و CSRF در کار نیست؛ هر درخواست مستقل و بی‌حالت است. توکن نباید در نشانیِ URL، پارامترِ پرس‌وجو یا کدِ سمتِ مرورگر قرار بگیرد، چون در لاگِ سرور، لاگِ شبکهٔ توزیعِ محتوا و تاریخچهٔ مرورگر ثبت می‌شود.

curl -H "Authorization: Bearer sn_xxxxxxxx" \
     https://servernet.cloud/api/v1/ping

دامنه‌های دسترسی

readخواندنِ حساب، سرویس‌ها، فاکتورها و اعتبار
domains:readخواندنِ دامنه‌ها، استعلامِ قیمت و موجودی
domains:writeثبت و تمدیدِ دامنه — از اعتبارِ حساب خرج می‌کند
domains:manageتغییرِ نام‌سرور و تمدیدِ خودکارِ دامنه‌های موجود
tunnel:readخواندنِ اکانت‌های تونلِ WireGuard-روی-TCP سرورِ اکسیت
tunnel:writeساخت و حذفِ اکانتِ تونل — کلیدِ خصوصی فقط یک بار برمی‌گردد

دسترسیِ نوشتن به‌طور ضمنی شاملِ خواندن است؛ عکسِ آن هرگز برقرار نیست. توصیهٔ ما صدورِ توکنِ جداگانه به‌ازای هر محیط است — یکی فقط‌خواندنی برای گزارش‌گیری، یکی نوشتنی و مقیدشده به IP برای سرورِ صورت‌حساب. توکنِ لورفتهٔ فقط‌خواندنی هیچ هزینه‌ای تولید نمی‌کند.

۳قرارداد پاسخ

هر پاسخ یک پوششِ JSON با شکلِ ثابت دارد. منطقِ شرطیِ سرویس‌گیرنده باید روی شناسهٔ ماشین‌خوانِ error بنشیند، نه روی متنِ message. متن قابلِ بومی‌سازی و ویرایش است و بخشی از قراردادِ پایدار نیست؛ شناسه‌ها بخشی از قرارداد نسخهٔ ۱ هستند و تا انتشارِ نسخهٔ بعدی حذف یا تغییرِ معنا نمی‌دهند.

{"ok": true,  "data": { ... }}
{"ok": false, "error": "insufficient_credit", "message": "..."}
به کدِ وضعیتِ HTTP به‌تنهایی اتکا نکنید؛ همیشه فیلدِ ok را ارزیابی کنید. این یک محافظه‌کاریِ نظری نیست: چند سرویسِ بالادستیِ همین زنجیره — از جمله رجیسترار و درگاهِ پرداخت — روی خطا هم کدِ ۲۰۰ برمی‌گردانند و نتیجهٔ واقعی را فقط در بدنه می‌گذارند. سرویس‌گیرنده‌ای که فقط کدِ وضعیت را می‌سنجد، شکست را موفقیت می‌خواند.

۴نقاط پایانی

GET /api/v1/ping آزمون اتصال، سطح و اعتبار read
GET /api/v1/tlds قیمت پسوندها (ثبت/تمدید/انتقال) domains:read
POST /api/v1/domains/check استعلام موجودی و قیمت domains:read
GET /api/v1/domains فهرست دامنه‌های شما domains:read
GET /api/v1/domains/{domain} جزئیات، انقضا، وضعیت domains:read
POST /api/v1/domains ثبت — از اعتبار کسر می‌شود domains:write
POST /api/v1/domains/{domain}/renew تمدید — از اعتبار کسر می‌شود domains:write
PUT /api/v1/domains/{domain}/nameservers تغییر نام‌سرور domains:manage
POST /api/v1/domains/{domain}/lock روشن کردن قفل انتقال domains:manage
POST /api/v1/domains/{domain}/auto-renew تمدید خودکار domains:manage

استعلام موجودی و قیمت

POST https://servernet.cloud/api/v1/domains/check
{"domain": "example.com", "tlds": ["com", "net"]}

{"ok": true, "data": [{
  "domain": "example.com", "state": "free", "available": true,
  "currency": "IRT",
  "price": {"register": 1150000, "renew": 1250000, "retail": 1320000},
  "discount_pct": 12.88, "price_floored": false
}]}

منطقِ سرویس‌گیرنده باید روی state تصمیم بگیرد، نه روی بولینِ available. مقدارِ unchecked به‌معنای «استعلام قطعی نشد» است و باید مثلِ یک خطای گذرا با تلاشِ دوباره برخورد شود، نه مثلِ «ثبت‌شده». تقلیلِ این شش حالت به یک بولین یک بار در همین سامانه به کاربران گفت نامِ انتخابی‌شان گرفته شده در حالی که آزاد بود.

free قابلِ ثبت premium قابلِ ثبت، با قیمت‌گذاریِ پرمیومِ رجیستری taken ثبت‌شده unchecked استعلام قطعی نشد — قابلِ تلاشِ دوباره unsupported این پسوند در کاتالوگِ فروشِ ما نیست no_price قابلِ ثبت، ولی قیمتِ قابلِ اتکا در دسترس نیست

پرچمِ price_floored با مقدارِ درست یعنی تخفیفِ سطحِ شما روی آن پسوند به‌طور کامل اعمال نشده، چون قیمتِ حاصل به کفِ حاشیهٔ ما رسیده است. این وضعیت پنهان نمی‌شود و در بخشِ قیمت‌گذاری کامل توضیح داده شده.

ثبت دامنه

POST https://servernet.cloud/api/v1/domains
Idempotency-Key: your-order-12345
{"domain": "example.com", "years": 1,
 "nameservers": ["ns1.you.com", "ns2.you.com"]}

{"ok": true, "data": {
  "domain": "example.com", "status": "pending",
  "order_state": "registered", "registrant": "reseller",
  "charged": 1265000, "currency": "IRT"
}}
order_state
registeredحالتِ نهایی — دامنه نزدِ رجیستری ثبت شدهاقدامِ دیگری لازم نیست
pendingحالتِ غیرنهایی — سفارش پذیرفته و در صفِ اجراستبا فاصلهٔ فزاینده وضعیتِ دامنه را استعلام کنید؛ سفارشِ تازه ندهید
manualحالتِ غیرنهایی — نیازمند بررسیِ انسانی نزدِ مامبلغ نگهداری می‌شود و نتیجه اعلام خواهد شد
failedحالتِ نهایی — ثبت انجام نشدمبلغ به‌طور کامل به اعتبارِ شما بازگردانده می‌شود
حالتِ pending یک شکست نیست و نباید مثلِ شکست پردازش شود. تفسیرِ آن به‌عنوان خطا و ارسالِ سفارشِ دوباره می‌تواند دامنه‌ای را که همان لحظه در حالِ ثبت است دوباره خریداری کند. کلیدِ یکتاسازی دقیقاً برای مهارِ همین حالت طراحی شده و ارسالِ آن روی هر عملیاتِ پولی شرطِ درستیِ یکپارچه‌سازی است.

۵یکتاسازی و تلاش دوباره

سرور درخواستِ بدونِ هدرِ Idempotency-Key را هم می‌پذیرد، ولی در آن حالت **هیچ محافظتی در برابرِ تکرار وجود ندارد**؛ بنابراین ارسالِ آن روی هر عملیاتِ پولی شرطِ درستیِ هر یکپارچه‌سازی است. کلید حداکثر ۸۰ نویسه است و پیش از انجامِ کار روی یک ایندکسِ یکتای پایگاه‌داده تصاحب می‌شود، پس دو درخواستِ هم‌زمان با یک کلید هرگز به دو تراکنشِ مالی منجر نمی‌شوند. پاسخِ بازپخش‌شده از نظرِ محتوا با پاسخِ اصلی یکسان است و پرچمِ replayed دارد. اگر تلاشِ اول با خطا تمام شود کلید آزاد می‌شود — یکتاسازی یعنی «یک کار دو بار انجام نشود»، نه «یک خطا تا ابد تکرار شود».

کلیدِ تمدید باید تاریخِ انقضای جاری را در خود داشته باشد

اگر کلید تنها از نامِ دامنه مشتق شود، تمدیدِ دورهٔ بعدیِ همان دامنه کلیدِ یکسانی تولید می‌کند. سرور آن را تکراری تشخیص می‌دهد و پاسخِ دورهٔ قبل را بازپخش می‌کند: سامانهٔ شما موفقیت ثبت می‌کند، مشتری پرداخت می‌کند، و هیچ تمدیدی نزدِ رجیستری انجام نمی‌شود. این خرابی تا روزِ انقضا هیچ نشانه‌ای تولید نمی‌کند. کلید باید دستِ‌کم شاملِ نامِ دامنه، تاریخِ انقضای جاری و تعدادِ سال باشد.

sha256("renew|example.com|2027-01-01|1")

برای تلاشِ دوباره از عقب‌نشینیِ نمایی با پراکندگیِ تصادفی استفاده کنید و همان کلید را نگه دارید؛ کلیدِ تازه در تلاشِ دوباره کلِ محافظت را خنثی می‌کند. ماژول‌های رسمیِ ما این کلید را خودشان می‌سازند و نگه می‌دارند.

۶شناسه‌های خطا

missing_tokenهدرِ Authorization ارسال نشده
invalid_tokenتوکن شناسایی نشد
token_expiredتوکن منقضی شده — توکنِ تازه صادر کنید
token_revokedتوکن باطل شده است
ip_not_allowedIP مبدأ در فهرستِ مجازِ این توکن نیست
insufficient_scopeتوکن دامنهٔ دسترسیِ لازم را ندارد
panel_onlyاین عملیات از رابطِ برنامه‌نویسی در دسترس نیست
insufficient_creditاعتبار کافی نیست — مبلغِ لازم و موجودی در فیلدِ data آمده
daily_cap_reachedسقفِ خرجِ روزانهٔ حساب پر شده است
already_registeredدامنه در پرتفویِ فعالِ ما موجود است
renewal_in_progressتمدیدی برای همین دامنه در جریان است
request_in_progressدرخواستی با همین کلیدِ یکتاسازی هنوز در حالِ پردازش است
tld_blockedثبت در این پسوند موقتاً معلق است؛ هیچ مبلغی کسر نشد
tld_not_soldاین پسوند در کاتالوگِ فروش نیست
registrant_incompleteمشخصاتِ مالکِ ثبت‌شده در حسابِ شما ناقص است
no_priceقیمتِ قابلِ اتکا در دسترس نیست
lookup_failedاستعلام از رجیسترار قطعی نشد — قابلِ تلاشِ دوباره
registrar_rejectedرجیسترار تغییرِ درخواستی را نپذیرفت
validation_failedبارِ درخواست معتبر نیست — جزئیاتِ هر فیلد در data
bad_idempotency_keyکلیدِ یکتاسازی از ۸۰ نویسه بلندتر است
conflictهمین کلیدِ یکتاسازی قبلاً برای درخواستِ دیگری مصرف شده
invalid_domainنامِ دامنه از نظرِ نحوی معتبر نیست
not_foundاین دامنه در حسابِ شما نیست
not_registeredدامنه هنوز نزدِ رجیسترار ثبت نشده — عملیاتِ مدیریتی روی آن ممکن نیست
not_activeفقط دامنهٔ فعال تمدید می‌شود
already_yoursدامنه از قبل در حسابِ خودِ شماست
account_inactiveحسابِ نمایندگی در دسترس نیست
order_failedسفارش کامل نشد — هیچ مبلغی کسر نشده است

۷قیمت‌گذاری و سطح‌بندی

قیمتی که API برمی‌گرداند بهایِ خریدِ شماست: قیمتِ خرده‌فروشی پس از کسرِ تخفیفِ سطح. سطح از دو سنجه به‌طور هم‌زمان مشتق می‌شود — حجمِ خریدِ دوازده ماهِ گذشته و تعدادِ دامنهٔ فعالِ پرتفویتان — و روزانه بازبینی می‌گردد. قیمتِ برگشتی از استعلام تضمینِ اجرا نیست؛ مرجعِ تسویه همان استعلامِ تازه‌ای است که در لحظهٔ سفارش انجام می‌شود.

  • ارتقا آنی است و در همان لحظه‌ای اعمال می‌شود که حجمِ خرید از آستانه عبور کند.
  • تنزل تدریجی است: افتِ حجم ابتدا مهلت می‌گیرد و سپس حداکثر یک پله اعمال می‌شود. این عدمِ تقارن عمدی است.
  • سطحِ جاری، فاصله تا آستانهٔ بعدی و تاریخِ آخرین بازبینی در پنلِ نمایندگی و در پاسخِ نقطهٔ پایانیِ سلامت در دسترس است.

کفِ حاشیه

حاشیهٔ سودِ ما به‌ازای هر پسوند متفاوت است و از ساختارِ هزینهٔ همان رجیستری می‌آید. روی پسوندهای کم‌حاشیه — که در عمل پرتقاضاترین‌ها هم هستند — تخفیفِ سطحِ شما تنها تا کفی اعمال می‌شود که بالای بهایِ تمام‌شدهٔ ما بماند. هر جا این کف فعال شود، پاسخِ API پرچمِ price_floored را درست می‌گذارد و درصدِ مؤثرِ اعمال‌شده را جداگانه برمی‌گرداند.

افشای این محدودیت یک تصمیمِ آگاهانه است. کفِ اعلام‌نشده اختلافی می‌سازد که سرویس‌گیرنده نمی‌تواند حسابش را ببندد و تنها راهِ کشفش مغایرت‌گیریِ دستیِ فاکتورهاست — یعنی همان چیزی که یک برنامهٔ وفاداری قرار بود از بین ببرد.

۸سهمیه‌ها و محدودیت‌ها

درخواست‌های خواندنی۱۲۰ / ۱ دقیقه
استعلام قیمت و موجودی۶۰ / ۱ دقیقه
عملیات نوشتنی۲۰ / ۱ دقیقه
بیشینهٔ دورهٔ هر سفارش (سال)۱۰
بیشینهٔ توکنِ فعالِ هم‌زمان۲۰

عبور از سقفِ نرخ پاسخِ ۴۲۹ می‌گیرد و باید با عقب‌نشینی مدیریت شود، نه با فراخوانیِ موازیِ بیشتر. افزون بر این، هر حساب یک سقفِ خرجِ روزانه دارد که در پنلِ نمایندگی قابلِ تنظیمِ رو به پایین است. این سقف یک محافظِ محدودکنندهٔ خسارت است: در سناریوی افشای توکن، بیشینهٔ زیانِ ممکن پیش از آنکه کسی متوجه شود به همان عدد محدود می‌مانَد. توصیه می‌شود آن را روی چند برابرِ گردشِ روزانهٔ واقعی‌تان تنظیم کنید، نه بیشتر.

۹عملیاتِ عمداً خارج از رابط

موارد زیر پیاده‌سازی‌نشده نیستند؛ آگاهانه از سطحِ دسترسیِ توکن کنار گذاشته شده‌اند. معیار روشن است: عملیاتی که با یک توکنِ افشاشده کنترلِ دامنهٔ مشتریِ نهایی را منتقل می‌کند، تنها با احرازِ انسانی در پنل انجام می‌شود. قفلِ انتقال از رابط فقط قابلِ روشن‌شدن است — عملیاتی که محافظت اضافه می‌کند بی‌خطر است، عملیاتی که محافظت را برمی‌دارد نیست.

auth_codeکدِ انتقال (EPP) — کلیدِ مالکیتِ دامنه است؛ اگر از API برگردد، در لاگِ WHMCS و Cloudflare می‌نشیند.
transfer_unlockخاموش‌کردنِ قفلِ انتقال — پیش‌نیازِ بردنِ دامنه.
registrant_changeتغییرِ مالکِ ثبت‌شده — انتقالِ مالکیت است، نه ویرایشِ اطلاعات.
dnsمدیریت رکوردهای DNS در دامنهٔ این رابط نیست؛ نام‌سرورِ خودتان یا ارائه‌دهندهٔ DNS دلخواهتان را ست کنید.
در نسخهٔ جاری، مالکِ ثبت‌شده نزدِ رجیستری حسابِ نمایندگیِ شماست، نه مشتریِ نهایی. اگر ماژول یا کدِ شما مشخصاتِ تماسِ مشتری را ارسال کند، این فیلدها نادیده گرفته و ذخیره نمی‌شوند. انتقالِ دادهٔ هویتیِ مشتریِ نهایی به یک مسیرِ دادهٔ مستقل نیاز دارد — رضایتِ صریح، توافق‌نامهٔ پردازش، سیاستِ نگهداری و مسیرِ حذف — و تا آماده‌شدنِ آن، پذیرشِ خاموشِ چنین داده‌ای بدتر از نپذیرفتنش است.
پسوندهای ملیِ ایران از این مسیر عرضه نمی‌شوند. بهایِ آنها از راهِ رجیسترارِ بین‌المللی چند ده برابرِ تعرفهٔ مستقیمِ ایرنیک است، پس استعلامشان حالتِ unsupported برمی‌گرداند و اساساً هیچ قیمتی تولید نمی‌شود. این محدودیتِ عرضه است، نه محدودیتِ فنی، و در نقشهٔ راه پیگیری می‌شود.

۱۰ماژول‌های رسمی

دو پیاده‌سازیِ مرجع نگهداری می‌شوند که همین رابط را مصرف می‌کنند و هر دو از پنلِ نمایندگی قابلِ دریافت‌اند. اگر پشتهٔ شما یکی از این دو است، ماژول را به یکپارچه‌سازیِ دست‌نویس ترجیح دهید: محافظ‌های مالی از پیش در آنها پیاده شده‌اند.

WHMCS modules/registrars/servernet/

یک ماژولِ رجیسترارِ استاندارد. در پوشهٔ رجیسترارهای WHMCS قرار می‌گیرد و تنها به توکن نیاز دارد. استعلام، ثبت، تمدید، مدیریت نام‌سرور، قفلِ انتقال، همگام‌سازیِ وضعیت و درون‌ریزیِ جدولِ قیمت را پوشش می‌دهد و کلیدِ یکتاسازی را — با احتسابِ تاریخِ انقضا — خودش می‌سازد.

WordPress + WooCommerce wp-content/plugins/servernet-domains/

یک افزونهٔ وردپرس با یکپارچگیِ اختیاریِ ووکامرس. کدِ کوتاه رابطِ جستجو را رندر می‌کند؛ با ووکامرسِ فعال، دامنه به سبد افزوده می‌شود، مشتری از درگاهِ خودِ شما پرداخت می‌کند و ثبت پس از تأییدِ پرداخت به‌طور خودکار اجرا می‌شود. افزونه روی نصبِ بدونِ ووکامرس هم بی‌خطا بالا می‌آید.

سه محافظِ مالی که ماژول‌ها پیاده کرده‌اند — و یکپارچه‌سازیِ دست‌نویس هم باید بکند
  1. قیمت هرگز از سمتِ مرورگر پذیرفته نمی‌شود. در لحظهٔ افزودن به سبد، قیمت مجدداً از این رابط استعلام و جایگزین می‌شود. بی‌این محافظ، یک درخواستِ دست‌ساز می‌تواند دامنه‌ای گران را به مبلغِ دلخواه واردِ سبد کند؛ تسویه با بهایِ واقعی از اعتبارِ شما انجام می‌شود و مابه‌التفاوت زیانِ شماست.
  2. پیش از اجرای ثبت، بهایِ خرید با مبلغِ لحظهٔ سفارش مقایسه می‌شود. اگر افزایش از آستانهٔ تعریف‌شده بگذرد، ثبتِ خودکار انجام نمی‌شود و سفارش برای تصمیمِ انسانی معلق می‌مانَد. فاصلهٔ میانِ افزودن به سبد و پرداخت می‌تواند روزها باشد و در آن فاصله نرخِ ارز جابه‌جا می‌شود.
  3. کلیدِ یکتاسازی از شناسهٔ سطرِ سفارش مشتق می‌شود، نه از شناسهٔ سفارش. یک سفارش می‌تواند چند دامنه داشته باشد و ووکامرس یک سفارش را از چند مسیرِ مستقل — وب‌هوکِ درگاه، بازگشتِ کاربر و تغییرِ دستیِ مدیر — پرداخت‌شده علامت می‌زند.

۱۱نقشهٔ راه

موارد زیر برنامه‌ریزی شده‌اند ولی هنوز در رابطِ نسخهٔ ۱ منتشر نشده‌اند. تا لحظهٔ انتشار، فراخوانیِ نقطهٔ پایانیِ متناظر پاسخِ ۴۰۴ می‌گیرد. افزودنِ نقطهٔ پایانیِ تازه یک تغییرِ سازگار است و نسخهٔ رابط را بالا نمی‌برد؛ سرویس‌گیرندهٔ شما نباید با دیدنِ فیلدِ ناشناخته در پاسخ خطا بدهد.

transferانتقالِ دامنه از رجیسترارِ دیگر — ارسالِ کدِ انتقال، پیگیریِ وضعیتِ درخواست و تسویهٔ سالِ اضافه‌شده. در دستِ توسعه است. توجه: نقطهٔ پایانیِ فهرستِ پسوندها از هم‌اکنون قیمتِ انتقال را برمی‌گرداند تا بتوانید جدولِ قیمتِ خود را کامل بسازید؛ ولی عملیاتِ انتقال هنوز قابلِ فراخوانی نیست.
irعرضهٔ پسوندهای ملیِ ایران از راهِ اتصالِ مستقیم، به‌جای رجیسترارِ بین‌المللی.
webhookاعلانِ رویداد به نشانیِ شما، تا برای تغییرِ حالتِ سفارش‌های غیرنهایی به استعلامِ دوره‌ای نیاز نباشد.
contactمسیرِ دادهٔ مالکِ ثبت‌شده به تفکیکِ مشتریِ نهایی، همراه با سازوکارِ رضایت و حذف.

داشبورد نسخهٔ PDF