> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leviacloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Managed database

> Buat database, ambil kredensial, kelola user, backup, PITR, dan read replica.

Endpoint database butuh `database:read` (baca) atau `database:write` (ubah). Semua jawaban yang memuat password juga butuh `database:write`. Key lama tanpa scope tidak punya akses database sama sekali. Lihat [Scope](https://docs.leviacloud.com/konsep/scope.md#endpoint-yang-mengembalikan-password).

## Buat database

**1. Pilih engine, versi, dan paket**

```bash theme={null}
curl -s "$LEVIA_API/databases/engines?region_id=$REGION&zone_id=$ZONE" -H "Authorization: Bearer $LEVIA_KEY"
curl -s "$LEVIA_API/databases/plans" -H "Authorization: Bearer $LEVIA_KEY"
```

Dengan `zone_id`, versi yang `available: false` belum ada di zona itu; pilih zona lain (`zone_ids`) atau versi lain. Harga paket dalam Rupiah per database.

**2. Buat**

```bash theme={null}
curl -s -X POST "$LEVIA_API/databases" \
  -H "Authorization: Bearer $LEVIA_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "orders-db",
    "engine": "postgres",
    "engine_version": "16",
    "plan_id": "'$DB_PLAN'",
    "region_id": "'$REGION'",
    "zone_id": "'$ZONE'"
  }'
```

Database ditagih seperti dari dashboard; saldo diperiksa lebih dulu.

**3. Tunggu running**

Status `provisioning` sampai `running` (beberapa menit). Pantau `GET /databases/{id}`.

**4. Ambil info koneksi**

```bash theme={null}
curl -s "$LEVIA_API/databases/$DB/connection" -H "Authorization: Bearer $LEVIA_KEY"
```

Berisi URI, host, port, nama database, user admin, dan **password admin**. Butuh `database:write`. Jangan simpan jawaban ini di log.

Field pembuatan lain:

| Field | Arti |
| - | - |
| `name` | 2–48 karakter: huruf kecil, angka, tanda hubung; diawali huruf |
| `engine` | `postgres`, `mysql`, `redis`, `mongodb`, `kafka` (yang ditawarkan tercantum di `GET /databases/engines`) |
| `ha_mode` | `standalone` (bawaan), `high_availability`, atau `multi_zone`: standby sinkron, PostgreSQL saja, ditagih 2× paket. `multi_zone` di region yang baru punya satu zona aktif ditolak `422`; pakai `high_availability`. |
| `vpc_id`, `subnet_id` | Tanpa ini, VPC default organisasi di region itu |
| `backup_retention_days` | Retensi backup harian 1–14 hari (bawaan 7) |
| `point_in_time_recovery` | `true` = PITR sebagai metode backup (PostgreSQL) |
| `public_access_enabled`, `allowed_ips` | Akses publik; butuh minimal satu IP/CIDR di `allowed_ips` |
| `ssl_mode` | `disable`, `require`, `verify_ca`, `verify_full` |

## Start, stop, restart

| Aksi | Endpoint | Syarat |
| - | - | - |
| Matikan | `POST /databases/{id}/stop` | `running`. Database yang mati tetap ditagih untuk disknya. |
| Nyalakan | `POST /databases/{id}/start` | `stopped` |
| Restart | `POST /databases/{id}/restart` | `running` |

## Password admin

`POST /databases/{id}/reset-password` membuat password admin baru dan mengembalikannya **sekali** di jawaban (setelah itu hanya lewat info koneksi). `200` dengan `applied: true` = sudah berlaku; `202` dengan `applied: false` = masih diterapkan, password lama berlaku sampai selesai.

## User dan database logis

```bash theme={null}
# Database logis (CREATE DATABASE)
curl -s -X POST "$LEVIA_API/databases/$DB/logical-databases" \
  -H "Authorization: Bearer $LEVIA_KEY" -H "Content-Type: application/json" \
  -d '{"name": "app"}'

# User dengan akses ke database "app"; tanpa "password", password dibuat platform
curl -s -X POST "$LEVIA_API/databases/$DB/users" \
  -H "Authorization: Bearer $LEVIA_KEY" -H "Content-Type: application/json" \
  -d '{"username": "app_user", "databases": ["app"]}'
```

* User dan database logis dibuat secara asinkron (`202`): status `creating` sampai `active`.
* Password user baru dikembalikan **sekali** di jawaban `POST …/users`. Simpan saat itu juga.
* `PUT /databases/{id}/users/{username}/grants` dengan `{"databases": [...]}` menggantikan **seluruh** daftar database logis yang boleh diakses user (hak ALL); `[]` mencabut semuanya.
* `POST /databases/{id}/users/{username}/rotate-password` membuat password baru (atau pakai `new_password`), dikembalikan sekali. Password lama berlaku sampai status user kembali `active`.
* User admin tidak bisa dihapus, dan database logis awal tidak bisa dihapus.
* Perubahan user, backup, atau penghapusan saat task sebelumnya masih berjalan ditolak `409`; ulangi beberapa detik kemudian.

> [!WARNING]
>
> Pada replay `Idempotency-Key`, field `password` berisi `null`. Bila password hilang, buat yang baru dengan reset/rotate. Lihat [Idempotency](https://docs.leviacloud.com/konsep/idempotency.md#password-tidak-pernah-disimpan).

## Backup dan restore

| Aksi | Endpoint | Catatan |
| - | - | - |
| Daftar restore point | `GET /databases/{id}/backups` | Harian (`automatic: true`, dipangkas sesuai retensi) dan manual (`automatic: false`) |
| Backup manual | `POST /databases/{id}/backups` | Disimpan sampai dihapus. Status `creating` sampai `ready`. |
| Hapus backup | `DELETE /databases/{id}/backups/{backup_id}` | |
| Restore di tempat | `POST /databases/{id}/backups/{backup_id}/restore` | **Menimpa** data database ini. Status `maintenance` selama restore. Tidak untuk database HA, read replica, atau database yang punya replica. |
| Restore ke database baru | `POST /databases/{id}/backups/{backup_id}/restore-to-new` | Database baru (ditagih biasa) dengan `name` dan `plan_id`; disk paket tidak boleh lebih kecil dari sumber. Subnet harus di zona backup. |

### Point-in-Time Recovery (PostgreSQL)

* `GET /databases/{id}/pitr`: status dan jendela pemulihan (`earliest_restorable_at` … `latest_restorable_at`).
* `PUT /databases/{id}/pitr`: menyalakan PITR sebagai metode backup (backup harian dimatikan; database direstart sekali, `202`), atau mengubah `retention_days` / `full_backup_interval_hours` bila sudah menyala (`200`).
* `DELETE /databases/{id}/pitr`: hanya bila ada metode backup lain; bila PITR satu-satunya metode → `422`.

Restore ke titik waktu tertentu belum tersedia lewat API.

## Read replica (PostgreSQL)

```bash theme={null}
curl -s -X POST "$LEVIA_API/databases/$DB/replicas" \
  -H "Authorization: Bearer $LEVIA_KEY" -H "Content-Type: application/json" \
  -d '{"name": "orders-db-replica-1"}'
```

* Hanya untuk PostgreSQL yang sedang berjalan. Replica ditagih seperti database dengan paketnya (`plan_id` kosong = paket primary).
* Replica hanya baca; login dengan user dan password primary (`credentials_from` di info koneksi). Keadaan replikasi ada di `replication.state`.
* `POST /databases/{id}/replicas/{replica_id}/promote` melepas replica menjadi database mandiri yang bisa ditulis. Tidak bisa dibatalkan.
* Replica juga tampil di `GET /databases` dengan `role: replica`.

## Akses publik

**1. Isi allowlist**

```bash theme={null}
curl -s -X PUT "$LEVIA_API/databases/$DB/allowed-ips" \
  -H "Authorization: Bearer $LEVIA_KEY" -H "Content-Type: application/json" \
  -d '{"allowed_ips": ["203.0.113.7/32"]}'
```

Menggantikan seluruh daftar. Selama akses publik menyala, daftar tidak boleh kosong.

**2. Nyalakan**

```bash theme={null}
curl -s -X PUT "$LEVIA_API/databases/$DB/public-access" \
  -H "Authorization: Bearer $LEVIA_KEY" -H "Content-Type: application/json" \
  -d '{"enabled": true}'
```

Memasang IP publik (ditagih per jam) yang hanya bisa dihubungi dari `allowed_ips`. Database di subnet privat tidak bisa punya akses publik.

## Hapus database

`DELETE /databases/{id}` menghapus database beserta VM, disk, dan alamat publiknya, dan menghentikan tagihannya. Hapus read replica-nya dulu. Jawaban `202`; database `deleting` (tidak ditagih) lalu hilang (`404`).

## Belum tersedia lewat API

Resize database, failover HA manual, restore PITR ke titik waktu, perubahan konfigurasi engine, metrik, dan sertifikat CA.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.