Panduan API

Mulai memakai AtlasNodes API: autentikasi, aturan request, dan contoh siap salin.

URL dasar

Semua endpoint memakai HTTPS dan JSON (UTF-8) di bawah URL dasar berikut. Versi API ada di path (v1); perubahan yang tidak kompatibel akan memakai versi baru.

url
https://app.atlasnodes.com/api/v1

Setiap response membawa header X-Request-Id. Sertakan nilainya saat menghubungi support.

Autentikasi

Kirim API key di header Authorization dengan skema Bearer. Key berawalan cvps_live_ dan hanya ditampilkan sekali saat dibuat — simpan di secret manager, jangan di repository.

shell
curl -s "$CLOUDVPS_API/regions" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY"

Key tidak valid, kedaluwarsa, atau dicabut → 401 unauthenticated. API key hanya untuk endpoint Customer API (katalog, wallet, billing, SSH key, server, invoice, limit akun); endpoint panel lain (akun, sesi, API key) → 403 forbidden.

Membuat API key

  1. Buka API Keys → Buat API key, beri nama yang menjelaskan pemakainya (mis. "terraform-prod").
  2. Kedaluwarsa (opsional, maksimal 2 tahun): key ditolak setelah tanggal tersebut.
  3. Akses: Penuh untuk otomasi yang membuat/mengubah VPS, atau Hanya baca untuk monitoring & laporan. Key hanya baca hanya boleh GET (password root juga tidak dapat diambil); request lain → 403 api_key_read_only.
  4. Batasi IP (opsional): satu IPv4/IPv6 atau CIDR per baris, maksimal 20 (mis. 203.0.113.10, 198.51.100.0/24, 2001:db8::/48). Kosong = semua IP. Request dari IP lain → 403 api_key_ip_not_allowed; details.ip berisi IP Anda menurut AtlasNodes, isi daftar tidak pernah dikirim.
  5. Konfirmasi dengan password akun (dan kode 2FA bila aktif). Nama, akses, dan daftar IP dapat diubah kapan saja lewat tombol Ubah; perubahan berlaku pada request berikutnya. Maksimal 10 key aktif per akun.

Pemilik akun mendapat notifikasi bila key dipakai dari IP di luar daftar (maksimal sekali per jam per key).

Rate limit

Kuota dihitung per API key dalam jendela bergeser 60 detik (default 60 request/menit; nilai aktual ada di X-RateLimit-Limit). Request yang ditolak karena endpoint khusus panel atau key hanya baca juga dihitung; penolakan IP allowlist dihitung per IP pemanggil, bukan per key.

X-RateLimit-Limit
Kuota per menit.
X-RateLimit-Remaining
Sisa kuota di jendela berjalan.
X-RateLimit-Reset
Waktu (epoch detik) saat satu slot kuota tersedia lagi.

Saat kuota habis: 429 rate_limited dengan header Retry-After dan error.details.retry_after (detik). Tunggu selama itu sebelum mencoba lagi; gunakan backoff eksponensial untuk retry lain. Terpisah dari kuota key: lebih dari 30 request gagal autentikasi per menit dari satu IP (key tidak valid, akun ditangguhkan, atau IP di luar daftar; IPv6 dihitung per /64) juga dibalas 429 rate_limited dengan Retry-After, tanpa header X-RateLimit-*.

http
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1791181212

{"error":{"code":"rate_limited","message":"Too many requests. Try again later.","details":{"retry_after":12},"request_id":"0b7c9d2e4f614a3b8c5d6e7f8a9b0c1d"}}

Idempotency-Key

Request yang membuat resource atau memotong saldo WAJIB membawa header Idempotency-Key (tanpa header → 428 idempotency_key_required):

  • POST /servers
  • POST /servers/{id}/reinstall
  • POST /servers/{id}/reset-password
  • POST /servers/{id}/resize
  • POST /servers/{id}/ip-addons
  • POST /servers/{id}/volumes
  • PATCH /servers/{id}/volumes/{volumeId}
  • POST /invoices/{id}/pay

Request mutasi lain (POST/DELETE) boleh membawanya; aturan yang sama berlaku bila dikirim.

  • Gunakan nilai unik per operasi (disarankan UUID v4), 1–255 karakter ASCII tanpa spasi. Kunci berlaku 24 jam per akun dan endpoint.
  • Retry dengan kunci DAN body yang sama mengembalikan response yang tersimpan (status sama, header Idempotent-Replayed: true) tanpa membuat VPS kedua atau memotong saldo dua kali.
  • Kunci yang sama dengan body berbeda → 422 idempotency_key_mismatch. Request pertama masih diproses → 409 idempotency_in_progress (coba lagi beberapa detik kemudian).
  • Response error tidak disimpan: setelah error (mis. 422 insufficient_balance) Anda boleh mengulang dengan kunci yang sama setelah memperbaiki penyebabnya.

Format error

Semua error memakai format yang sama. code stabil (bahasa Inggris) — pakai untuk logika program; message mengikuti header Accept-Language: id atau en. request_id sama dengan header X-Request-Id.

json
{
  "error": {
    "code": "api_key_ip_not_allowed",
    "message": "Your IP address is not allowed to use this API key.",
    "details": { "ip": "203.0.113.7" },
    "request_id": "0b7c9d2e4f614a3b8c5d6e7f8a9b0c1d"
  }
}
StatusCodeArti
400validation_errorBody/query tidak valid; rincian per field di details.fields.
401unauthenticatedAPI key tidak ada, tidak valid, kedaluwarsa, atau dicabut.
403forbiddenEndpoint tidak dapat diakses dengan API key (khusus panel).
403account_suspendedAkun ditangguhkan.
403email_not_verifiedVerifikasi email dulu sebelum membuat VPS.
403server_suspendedVPS ditangguhkan (mis. tagihan belum dibayar).
403api_key_ip_not_allowedIP pemanggil tidak ada di daftar IP key ini (details.ip).
403api_key_read_onlyKey hanya baca dipakai untuk request selain GET.
404not_foundResource tidak ada atau bukan milik Anda.
409server_busyMasih ada aksi lain yang berjalan untuk VPS ini.
409invalid_stateAksi tidak dapat dilakukan pada status VPS saat ini.
409price_changedTarif berubah sejak Anda melihatnya; ambil tarif terbaru lalu kirim ulang.
409idempotency_in_progressLihat bagian Idempotency-Key.
422insufficient_balanceSaldo tidak cukup (details.required, details.available).
422limit_exceededBatas akun tercapai (mis. jumlah VPS).
422out_of_stockStok paket di region tersebut sedang habis — cek GET /catalog/availability lalu pilih region/paket lain.
422plan_unavailable · region_unavailable · image_unavailablePlan, region, atau image tidak tersedia.
422idempotency_key_mismatchLihat bagian Idempotency-Key.
428idempotency_key_requiredLihat bagian Idempotency-Key.
429rate_limitedKuota habis; tunggu Retry-After detik.
503upstream_unavailableInfrastruktur VPS sementara tidak dapat dihubungi; coba lagi nanti.

Uang

Nominal uang selalu string desimal 2 digit disertai currency (mis. "6.00" + "USD"), tidak pernah number. Tarif per jam memakai 4–6 desimal (mis. "0.0090"). Simpan dan hitung sebagai desimal, bukan float.

Pagination

Endpoint daftar berikut menerima page (mulai 1) dan per_page (default 20, maksimal 100) dan mengembalikan meta:

  • GET /servers
  • GET /servers/{id}/actions
  • GET /servers/{id}/resizes
  • GET /wallet/transactions
  • GET /invoices
shell
curl -s "$CLOUDVPS_API/servers?page=2&per_page=50&status=running" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY"

# { "data": [ ... ], "meta": { "page": 2, "per_page": 50, "total": 73, "total_pages": 2 } }

Daftar katalog (/regions, /tiers, /plans, /images) dan /ssh-keys dikembalikan utuh tanpa meta.

Aksi asinkron

Membuat VPS, aksi power, reinstall, resize, reset password, dan hapus berjalan di latar belakang: response 202 berisi objek action berstatus pending. Poll action tersebut setiap 3–5 detik sampai status completed, failed, atau cancelled.

Satu VPS hanya menjalankan satu aksi pada satu waktu; aksi baru saat aksi lain berjalan → 409 server_busy. Field pending_action_id pada server menunjukkan aksi yang sedang berjalan.

Contoh curl

Contoh memakai variabel shell berikut. Ganti ID dengan nilai dari response sebelumnya.

shell
export CLOUDVPS_API="https://app.atlasnodes.com/api/v1"
export CLOUDVPS_API_KEY="cvps_live_..."   # dari halaman API Keys / from the API Keys page

Katalog: region, tier server, plan, dan OS image

shell
curl -s "$CLOUDVPS_API/regions" -H "Authorization: Bearer $CLOUDVPS_API_KEY"
curl -s "$CLOUDVPS_API/tiers"   -H "Authorization: Bearer $CLOUDVPS_API_KEY"
curl -s "$CLOUDVPS_API/plans"   -H "Authorization: Bearer $CLOUDVPS_API_KEY"
curl -s "$CLOUDVPS_API/images?region_id=REGION_ID" -H "Authorization: Bearer $CLOUDVPS_API_KEY"
curl -s "$CLOUDVPS_API/catalog/availability" -H "Authorization: Bearer $CLOUDVPS_API_KEY"

/images?region_id= hanya menampilkan OS yang tersedia di region tersebut. /catalog/availability menunjukkan stok per region & paket (available; remaining hanya bila ada batas stok).

Membuat VPS (Idempotency-Key wajib)

shell
curl -s -X POST "$CLOUDVPS_API/servers" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "hostname": "web-production",
    "region_id": "REGION_ID",
    "plan_id": "PLAN_ID",
    "image_id": "IMAGE_ID",
    "ssh_key_ids": ["SSH_KEY_ID"]
  }'

Response 202 berisi data.server (status pending) dan data.action. ssh_key_ids opsional (maksimal 1, dari GET /ssh-keys). Simpan Idempotency-Key yang sama bila Anda perlu mengulang request ini.

Memantau action sampai selesai

shell
# SERVER_ID = data.server.id, ACTION_ID = data.action.id
while true; do
  STATUS=$(curl -s "$CLOUDVPS_API/servers/SERVER_ID/actions/ACTION_ID" \
    -H "Authorization: Bearer $CLOUDVPS_API_KEY" | jq -r '.data.status')
  echo "$STATUS"
  case "$STATUS" in completed|failed|cancelled) break ;; esac
  sleep 5
done

Mengambil password root (sekali)

shell
curl -s "$CLOUDVPS_API/servers/SERVER_ID/initial-credentials" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY"

# { "data": { "username": "root", "password": "...", "expires_at": "..." } }

Tersedia setelah action create/reinstall selesai, hanya bisa diambil sekali dalam 60 menit. Membutuhkan key akses penuh.

Link console (noVNC)

shell
curl -s -X POST "$CLOUDVPS_API/servers/SERVER_ID/console-link" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY"

# { "data": { "url": "https://…/console-link#…", "expires_at": "..." } }
# Buka data.url di tab baru dalam 60 detik (sekali pakai).

Link halaman console untuk VPS running, berlaku 60 detik dan sekali pakai — cocok untuk diteruskan ke pelanggan reseller. Buka di tab baru (tidak bisa di-iframe). Membutuhkan key akses penuh.

Aksi power

shell
# start | shutdown | stop | restart
curl -s -X POST "$CLOUDVPS_API/servers/SERVER_ID/restart" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY"

start menyalakan, shutdown mematikan secara normal (ACPI), stop mematikan paksa, restart me-restart. Body kosong.

Reinstall OS

shell
curl -s "$CLOUDVPS_API/servers/SERVER_ID/images" -H "Authorization: Bearer $CLOUDVPS_API_KEY"

curl -s -X POST "$CLOUDVPS_API/servers/SERVER_ID/reinstall" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "image_id": "IMAGE_ID" }'

image_id harus salah satu dari GET /servers/{id}/images. Semua data di disk dihapus.

Mengubah paket (resize)

shell
curl -s "$CLOUDVPS_API/servers/SERVER_ID/resize-options" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY"

curl -s -X POST "$CLOUDVPS_API/servers/SERVER_ID/resize" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "plan_id": "TARGET_PLAN_ID",
    "expected_price_hourly": "0.0179",
    "expected_monthly_cap": "12.00",
    "accept_downtime": true
  }'

Hanya untuk VPS dengan billing per jam. Ambil price_hourly dan monthly_cap plan tujuan dari resize-options, lalu kirim sebagai expected_price_hourly / expected_monthly_cap dengan accept_downtime: true. Disk tidak pernah dikecilkan.

Menghapus VPS

shell
curl -s -X DELETE "$CLOUDVPS_API/servers/SERVER_ID" \
  -H "Authorization: Bearer $CLOUDVPS_API_KEY"

Response 202 dengan action delete. Penghapusan permanen, termasuk backup.

Saldo wallet

shell
curl -s "$CLOUDVPS_API/wallet" -H "Authorization: Bearer $CLOUDVPS_API_KEY"

# { "data": { "currency": "USD", "balance": "20.00", "available_balance": "20.00", ... } }

balance, available_balance, dan nominal lain berupa string desimal dalam currency.

Referensi lengkap

Semua endpoint, parameter, schema response, dan code error per endpoint ada di referensi interaktif. Spesifikasi mesin (OpenAPI 3) dapat dipakai untuk membuat client SDK.