همهٔ سیستم‌ها عملیاتی‌اند

راهنمای شروع

شروع سریع با API ایران‌کلاد

در چند دقیقه توکن می‌سازید، اولین درخواست را می‌فرستید و می‌بینید پاسخ‌ها، خطاها و محدودیت‌ها چطور کار می‌کنند. همهٔ نمونه‌ها را می‌توانید مستقیم کپی و اجرا کنید.

پیش از شروع

نشانی پایهٔ همهٔ درخواست‌ها https://iranclaud.ir/api/v1 است. همین نشانی بدون توکن هم پاسخ می‌دهد و نام سرویس، نسخه، نشانی مستندات و نام گروه‌های API را برمی‌گرداند؛ راه خوبی برای اطمینان از دسترسی شبکه پیش از ساخت توکن. مسیر دقیق هر endpoint را در مرجع ببینید.

بدون توکن
curl https://iranclaud.ir/api/v1

۱. ساخت توکن

  1. ۱ وارد حساب شوید و به صفحهٔ ساخت توکن بروید.
  2. ۲ یک نام توضیحی بنویسید (مثلاً «CI استقرار») و فقط دسترسی‌هایی را تیک بزنید که اسکریپت لازم دارد؛ فهرست کامل در بخش ۷ است.
  3. ۳ انقضا را انتخاب کنید: ۳۰، ۹۰ یا ۳۶۵ روز، یا بدون انقضا.
  4. ۴ توکن فقط همین یک بار نمایش داده می‌شود. همان لحظه آن را در جای امنی ذخیره کنید؛ اگر گم شد، باطلش کنید و توکن تازه بسازید.

توکن‌ها شکل ic_pat_xxxxxxxx_xxxx… دارند: پیشوند ثابت ic_pat_، هشت نویسهٔ شناسه و ۳۲ نویسهٔ مخفی. پیشوند ثابت کمک می‌کند ابزارهای اسکن کد، توکنی را که اشتباهی در مخزن کد قرار گرفته پیدا کنند.

۲. اولین درخواست

توکن را در هدر Authorization: Bearer <token> بفرستید. بهتر است آن را در یک متغیر محیطی نگه دارید تا در تاریخچهٔ shell و کد شما نماند. این درخواست فهرست سرورهای حساب را برمی‌گرداند و به دسترسی vm:read نیاز دارد.

curl
export IRANCLAUD_TOKEN="ic_pat_…"

curl -H "Authorization: Bearer $IRANCLAUD_TOKEN" \
  "https://iranclaud.ir/api/v1/vms?limit=10"
Python 3 · requests
import os, requests

r = requests.get(
    "https://iranclaud.ir/api/v1/vms",
    headers={"Authorization": f"Bearer {os.environ['IRANCLAUD_TOKEN']}"},
    params={"limit": 10},
    timeout=30,
)
r.raise_for_status()
for vm in r.json()["data"]:
    print(vm["uuid"], vm["status"], vm["public_ip"])
Node.js 18+ · fetch · فایل ‎.mjs
const res = await fetch("https://iranclaud.ir/api/v1/vms?limit=10", {
  headers: { Authorization: `Bearer ${process.env.IRANCLAUD_TOKEN}` },
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
for (const vm of body.data) console.log(vm.uuid, vm.status, vm.public_ip);

۳. ساخت سرور ابری با API

ابتدا شناسهٔ پلن و سیستم‌عامل را از فهرست‌های عمومی بخوانید؛ این دو درخواست توکن لازم ندارند. فیلد slug هر مورد همان مقداری است که در درخواست ساخت می‌فرستید.

فهرست پلن‌ها و سیستم‌عامل‌ها
curl https://iranclaud.ir/api/v1/plans
curl https://iranclaud.ir/api/v1/os-templates

سپس با توکنی که دسترسی vm:create دارد درخواست ساخت را بفرستید. فیلدهای plan_slug و os_template_slug الزامی‌اند؛ hostname اختیاری است (پایین‌تر را ببینید) و برای ورود می‌توانید رمز عبور (password)، کلید SSH (pubkey) یا هر دو (both) را انتخاب کنید. در نمونهٔ زیر، YOUR_SSH_KEY_UUID را با شناسهٔ کلید SSH خود عوض کنید؛ فهرست کلیدها و شناسه‌هایشان را GET /api/v1/account/ssh-keys برمی‌گرداند.

POST /api/v1/vms
curl -X POST "https://iranclaud.ir/api/v1/vms" \
  -H "Authorization: Bearer $IRANCLAUD_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "plan_slug": "mini",
    "os_template_slug": "debian-12",
    "auth_mode": "pubkey",
    "ssh_key_uuids": ["YOUR_SSH_KEY_UUID"]
  }'
  • پاسخ موفق کد 202 دارد؛ سرور ساخته شده و شناسهٔ آن در data.uuid و هدر Location است.
  • هزینهٔ ساعت اول همان لحظه از کیف پول کسر می‌شود. اگر موجودی کافی نباشد، پاسخ 422 با details.reason = insufficient_balance می‌گیرید.
  • وضعیت را با GET /api/v1/vms/{uuid} چند ثانیه یک بار بخوانید تا status به running برسد.
  • اگر پاسخ 503 با کد compute_unavailable بود، هزینهٔ ساعت اول کسر شده و سفارش پرداخت‌شده به‌طور خودکار ساخته می‌شود؛ درخواست را تکرار نکنید.
  • هر درخواست POST یک سرور تازه می‌سازد. اگر پاسخ به‌خاطر قطعی شبکه نرسید، پیش از تکرار فهرست سرورها را بخوانید تا سرور تکراری و هزینهٔ دوباره نسازید.
  • فیلد hostname فعلاً فقط بررسی می‌شود و هنگام ساخت اعمال نمی‌شود؛ پس از ساخت آن را با POST /api/v1/vms/{uuid}/security/hostname تنظیم کنید.

۴. قالب پاسخ و صفحه‌بندی

همهٔ پاسخ‌ها JSON هستند و یکی از سه شکل زیر را دارند. request_id را در گزارش‌های خود نگه دارید؛ همین شناسه در هدر X-Request-Id هم می‌آید و هنگام تماس با پشتیبانی پیگیری را سریع می‌کند.

JSON
// موفق، یک مورد
{ "data": { … }, "meta": { "request_id": "…" } }

// موفق، فهرست
{ "data": [ … ],
  "meta": { "request_id": "…", "next_cursor": null, "has_more": false, "total": 7 } }

// خطا
{ "error": { "code": "scope_missing", "message": "Token requires vm:write scope.",
             "details": { "required_scope": "vm:write" } },
  "meta":  { "request_id": "…" } }

صفحه‌بندی در همهٔ فهرست‌ها یکسان نیست؛ next_cursor در نسخهٔ v1 همیشه null و has_more همیشه false است:

  • فهرست سرورها (/vms) و تراکنش‌های کیف پول (/wallet/transactions) با limit (۱ تا ۲۰۰، پیش‌فرض ۵۰) و offset صفحه‌بندی می‌شوند و meta.total تعداد کل را می‌گوید. فهرست سرورها فیلتر status و جست‌وجوی q در شناسه، IP و نام سرور هم دارد.
  • تیکت‌ها (/tickets) و گزارش فعالیت (/activity) با page و per_page (۱ تا ۲۰۰، پیش‌فرض ۵۰) کار می‌کنند و فهرست را داخل data.items همراه با total و pages برمی‌گردانند.
  • بقیهٔ فهرست‌ها (DNS‏، CDN‏، کلیدهای SSH، فضای ذخیره‌سازی، دیتابیس، اپلیکیشن‌ها و…) صفحه‌بندی ندارند و همهٔ موارد را یک‌جا با meta.total برمی‌گردانند.

پارامترهای هر endpoint در مرجع آمده است.

۵. کدهای خطا

برنامهٔ خود را بر اساس error.code بنویسید، نه متن پیام؛ کدها ثابت‌اند و پیام ممکن است تغییر کند.

کدهای خطای API و معنی آن‌ها
کد HTTP معنی و راه‌حل
unauthenticated HTTP 401 هدر Authorization نیست یا با Bearer شروع نمی‌شود.
token_invalid HTTP 401 توکن نامعتبر، منقضی یا باطل‌شده است، یا حساب فعال نیست. توکن تازه بسازید.
scope_missing HTTP 403 توکن دسترسی لازم را ندارد؛ نام آن در details.required_scope آمده است.
not_found HTTP 404 منبع وجود ندارد یا متعلق به حساب شما نیست.
conflict HTTP 409 وضعیت فعلی اجازهٔ این کار را نمی‌دهد؛ مثلاً دامنه قبلاً ثبت شده یا زون هنوز تأیید نشده است.
not_supported HTTP 409 این کار برای این نوع سرور در دسترس نیست؛ مثلاً کنسول وب، تغییر رمز روت یا نام میزبان و بازیابی بکاپ در سرور اختصاصی. راه جایگزین در متن پیام خطا آمده است.
suspended_unpaid HTTP 409 سرور به‌دلیل کسری موجودی معلق است؛ روشن کردن، راه‌اندازی دوباره، بازیابی بکاپ و تغییر رمز یا نام میزبان رد می‌شود (خاموش کردن مجاز است). پس از شارژ کیف پول سرور خودکار روشن می‌شود.
topup_failed HTTP 402/422 خرید بستهٔ ترافیک انجام نشد: 402 یعنی موجودی کیف پول کافی نیست؛ 422 یعنی بسته اعمال نشد و مبلغ برگشت داده شد.
validation_failed HTTP 422 بدنه یا پارامترها نامعتبرند؛ فیلدهای مشکل‌دار در details.fields آمده‌اند.
rate_limited HTTP 429 از سقف درخواست گذشته‌اید؛ به اندازهٔ هدر Retry-After (ثانیه) صبر کنید.
internal_error HTTP 500 خطای پیش‌بینی‌نشده؛ request_id را برای پشتیبانی بفرستید.
compute_unavailable HTTP 503 سرویس ساخت و مدیریت سرور موقتاً در دسترس نیست؛ کمی بعد دوباره تلاش کنید.
backend_error HTTP 503 سرویس پشتیبان (مثلاً فضای ذخیره‌سازی) موقتاً پاسخ نمی‌دهد؛ دوباره تلاش کنید.
sync_failed HTTP 503 گروه قانون فایروال ذخیره شد اما روی سرور اعمال نشد؛ بعداً با POST /firewall/rulesets/{uuid}/sync دوباره اعمال کنید.

نشانی یا متدی که وجود ندارد قالب JSON بالا را ندارد: مسیر ناشناخته پاسخ متنی 404 Not Found و متد نادرست روی مسیر درست پاسخ 405 با هدر Allow می‌گیرد. اگر به‌جای JSON متن گرفتید، مسیر و متد را با مرجع مقایسه کنید.

۶. محدودیت نرخ

سقف‌ها برای هر توکن و هر نوع درخواست جداگانه حساب می‌شوند. پنجرهٔ دقیقه‌ای سر هر دقیقه و پنجرهٔ روزانه سر هر روز (UTC) از نو شروع می‌شود. درخواست‌های ردشده هم در شمارش حساب می‌شوند، پس پس از 429 تا پایان زمان Retry-After صبر کنید.

سقف درخواست برای هر توکن
نوع درخواست در دقیقه در روز
خواندن (GET)۱۲۰۵۰٬۰۰۰
تغییر (POST‏، PATCH‏، DELETE)۳۰۵٬۰۰۰
باز کردن کنسول سرور۱۰۲۰۰
مجموع همهٔ توکن‌های حساب—۱۰۰٬۰۰۰

هر پاسخی که از سد محدودیت بگذرد این هدرها را دارد (همه برای پنجرهٔ دقیقه‌ای):

  • X-RateLimit-Limit سقف دقیقه‌ای این نوع درخواست
  • X-RateLimit-Remaining تعداد باقی‌مانده در این دقیقه
  • X-RateLimit-Reset زمان شروع دقیقهٔ بعد به صورت Unix timestamp

نوع هر endpoint (خواندن، تغییر یا کنسول) کنار آن در مرجع آمده است. فهرست‌های عمومی پلن و سیستم‌عامل توکن نمی‌خواهند و در این سقف‌ها شمرده نمی‌شوند.

پاسخ 429 به‌جای آن‌ها هدر Retry-After (ثانیه) و در بدنه details.retry_after_sec دارد.

۷. دسترسی‌ها (scope)

هر endpoint، به‌جز فهرست‌های عمومی پلن و سیستم‌عامل، یک scope مشخص لازم دارد که کنار آن در مرجع آمده است. توکن را با کمترین دسترسی لازم بسازید: اسکریپت گزارش‌گیری فقط به scope‌های :read نیاز دارد. vm:destroy در فرم ساخت توکن هست اما هنوز endpointی برای حذف سرور با API وجود ندارد؛ حذف سرور فعلاً از پنل انجام می‌شود.

فهرست scope‌های توکن API
حوزه scope‌ها
سرور ابری
  • vm:read
  • vm:write
  • vm:create
  • vm:console
حذف سرور (به‌زودی)
  • vm:destroy
فایروال سرور
  • vm:firewall:read
  • vm:firewall:write
گروه‌های قانون فایروال
  • firewall:read
  • firewall:write
حساب و کلید SSH
  • account:read
  • account:write
DNS
  • dns:read
  • dns:write
CDN
  • edge:read
  • edge:toggle
پشتیبان‌گیری
  • backup:read
  • backup:write
ترافیک
  • traffic:read
  • traffic:topup
کیف پول
  • wallet:read
فضای ذخیره‌سازی
  • storage:read
  • storage:write
دیتابیس
  • database:read
  • database:write
وردپرس
  • wordpress:read
  • wordpress:write
نکست‌کلاد
  • nextcloud:read
  • nextcloud:write
مترموست
  • mattermost:read
  • mattermost:write
تیکت و فعالیت
  • tickets:read
  • tickets:write
  • activity:read

۸. نگهداری امن توکن

  • توکن را در متغیر محیطی یا بخش secrets سامانهٔ CI نگه دارید، نه در کد یا فایل‌های مخزن.
  • برای هر اسکریپت یا سرویس توکن جداگانه بسازید تا در صورت نشت، فقط همان یکی را باطل کنید.
  • برای توکن‌های موقت انقضا بگذارید و توکن‌های بی‌استفاده را در صفحهٔ توکن‌ها باطل کنید؛ آن‌جا زمان آخرین استفادهٔ هر توکن هم دیده می‌شود.
  • همیشه از نشانی https استفاده کنید. API توکن را فقط از هدر Authorization می‌خواند؛ آن را در نشانی (query string) یا لاگ‌ها نگذارید.

قدم بعدی