P
PUGUH

API Organizations

Referensi API lengkap untuk mengelola organisasi, anggota, kebijakan, branding, dan SSO di ARSAKA PUGUH.

Konvensi API

Semua response API PUGUH dikembalikan langsung sebagai JSON (tanpa wrapper {success, data}). Kode status HTTP menunjukkan keberhasilan atau kegagalan. Endpoint berpaginasi mengembalikan {items, total, page, page_size, has_next, has_prev}.

Ringkasan Endpoint

Organization CRUD

MethodEndpointDeskripsi
GET /api/v1/organizations Daftar organisasi
POST /api/v1/organizations Buat organisasi
GET /api/v1/organizations/{id} Detail organisasi
PATCH /api/v1/organizations/{id} Perbarui organisasi
DELETE /api/v1/organizations/{id} Hapus organisasi (soft delete)

Members

MethodEndpointDeskripsi
GET /api/v1/organizations/{id}/members Daftar anggota
POST /api/v1/organizations/{id}/members Undang anggota
PATCH /api/v1/organizations/{id}/members/{user_id} Perbarui role anggota
DELETE /api/v1/organizations/{id}/members/{user_id} Hapus anggota

Policies (Paket Business+)

MethodEndpointDeskripsi
GET /api/v1/organizations/{id}/policies Lihat kebijakan organisasi
PUT /api/v1/organizations/{id}/policies Perbarui kebijakan organisasi

Branding (Paket Business+)

MethodEndpointDeskripsi
GET /api/v1/organizations/{id}/branding Lihat konfigurasi branding
PUT /api/v1/organizations/{id}/branding Perbarui konfigurasi branding

SSO (Paket Business+)

MethodEndpointDeskripsi
POST /api/v1/sso/configurations Buat konfigurasi SSO
GET /api/v1/sso/configurations/{org_id} Lihat konfigurasi SSO
PUT /api/v1/sso/configurations/{org_id} Perbarui konfigurasi SSO

Daftar Organisasi

Mengembalikan daftar berpaginasi dari organisasi yang dimiliki pengguna yang terautentikasi.

http
GET /api/v1/organizations

Parameter Query

ParameterTipeDefaultDeskripsi
page int 1 Nomor halaman
page_size int 20 Item per halaman (maks 100)
type string Filter berdasarkan tipe: personal atau team
search string Cari berdasarkan nama organisasi

Response (200 OK)

json
{
  "items": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Corp",
      "slug": "acme-corp",
      "type": "team",
      "plan": "business",
      "member_count": 24,
      "is_active": true,
      "created_at": "2026-01-15T08:00:00Z",
      "updated_at": "2026-02-10T14:30:00Z"
    },
    {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "name": "Jane's Workspace",
      "slug": "janes-workspace",
      "type": "personal",
      "plan": "free",
      "member_count": 1,
      "is_active": true,
      "created_at": "2026-01-10T06:00:00Z",
      "updated_at": "2026-01-10T06:00:00Z"
    }
  ],
  "total": 2,
  "page": 1,
  "page_size": 20,
  "has_next": false,
  "has_prev": false
}

Buat Organisasi

Membuat organisasi tim baru. Setiap pengguna otomatis mendapatkan workspace personal saat mendaftar; endpoint ini untuk membuat organisasi tim tambahan.

http
POST /api/v1/organizations
Content-Type: application/json

Request Body

json
{
  "name": "Acme Corp",
  "slug": "acme-corp",
  "type": "team"
}

Field Request

FieldTipeWajibDeskripsi
name string Ya Nama tampilan (2-100 karakter)
slug string Tidak Identifier URL-friendly (otomatis dari nama jika tidak diisi)
type string Tidak team (default) atau personal

Response (201 Created)

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Corp",
  "slug": "acme-corp",
  "type": "team",
  "plan": "free",
  "is_active": true,
  "created_at": "2026-02-20T10:00:00Z",
  "updated_at": "2026-02-20T10:00:00Z"
}

Info

Pengguna yang membuat secara otomatis diberi role owner di organisasi baru.

Detail Organisasi

Mengembalikan informasi detail tentang organisasi tertentu.

http
GET /api/v1/organizations/{id}

Response (200 OK)

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Corp",
  "slug": "acme-corp",
  "type": "team",
  "plan": "business",
  "member_count": 24,
  "application_count": 3,
  "is_active": true,
  "settings": {
    "default_role": "member",
    "allow_member_invite": false
  },
  "created_at": "2026-01-15T08:00:00Z",
  "updated_at": "2026-02-10T14:30:00Z"
}

Perbarui Organisasi

Memperbarui detail organisasi. Hanya field yang disertakan dalam request body yang diubah.

http
PATCH /api/v1/organizations/{id}
Content-Type: application/json

Request Body

json
{
  "name": "Acme Corporation",
  "settings": {
    "default_role": "viewer",
    "allow_member_invite": true
  }
}

Field Request

FieldTipeDeskripsi
name string Nama tampilan organisasi
slug string Identifier URL-friendly (harus unik)
settings.default_role string Role default untuk anggota baru: member atau viewer
settings.allow_member_invite boolean Apakah anggota non-admin dapat mengundang orang lain

Response (200 OK)

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Corporation",
  "slug": "acme-corp",
  "type": "team",
  "plan": "business",
  "is_active": true,
  "settings": {
    "default_role": "viewer",
    "allow_member_invite": true
  },
  "updated_at": "2026-02-20T11:00:00Z"
}

Hapus Organisasi

Soft-delete organisasi. Organisasi dinonaktifkan dan ditandai sebagai dihapus tetapi data disimpan selama 30 hari sebelum penghapusan permanen.

http
DELETE /api/v1/organizations/{id}

Response (200 OK)

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "is_active": false,
  "deleted_at": "2026-02-20T12:00:00Z"
}

Peringatan

Hanya owner organisasi yang dapat menghapus organisasi. Menghapus organisasi menonaktifkan semua aplikasi terkait dan mencabut akses anggota secara langsung.

Daftar Anggota

Mengembalikan daftar berpaginasi dari anggota dalam organisasi.

http
GET /api/v1/organizations/{id}/members

Parameter Query

ParameterTipeDefaultDeskripsi
page int 1 Nomor halaman
page_size int 20 Item per halaman (maks 100)
role string Filter berdasarkan role: owner, admin, member, viewer
search string Cari berdasarkan nama atau email

Response (200 OK)

json
{
  "items": [
    {
      "user_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "email": "jane@acme.com",
      "full_name": "Jane Smith",
      "role": "owner",
      "status": "active",
      "accepted_at": "2026-01-15T08:00:00Z"
    },
    {
      "user_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "email": "bob@acme.com",
      "full_name": "Bob Johnson",
      "role": "admin",
      "status": "active",
      "accepted_at": "2026-01-20T09:30:00Z"
    },
    {
      "user_id": null,
      "email": "new@acme.com",
      "full_name": null,
      "role": "member",
      "status": "pending",
      "accepted_at": null
    }
  ],
  "total": 3,
  "page": 1,
  "page_size": 20,
  "has_next": false,
  "has_prev": false
}

Undang Anggota

Mengirimkan email undangan untuk bergabung ke organisasi. Jika email belum memiliki akun PUGUH, pengguna akan diminta untuk mendaftar terlebih dahulu.

http
POST /api/v1/organizations/{id}/members
Content-Type: application/json

Request Body

json
{
  "email": "new@acme.com",
  "role": "member"
}

Field Request

FieldTipeWajibDeskripsi
email string Ya Alamat email yang diundang
role string Ya Role yang diberikan: admin, member, atau viewer

Response (201 Created)

json
{
  "email": "new@acme.com",
  "role": "member",
  "status": "pending",
  "invited_at": "2026-02-20T10:00:00Z",
  "invited_by": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Info

Anda tidak dapat mengundang seseorang sebagai owner. Kepemilikan harus ditransfer secara eksplisit oleh owner saat ini.

Perbarui Role Anggota

Mengubah role anggota organisasi yang ada.

http
PATCH /api/v1/organizations/{id}/members/{user_id}
Content-Type: application/json

Request Body

json
{
  "role": "admin"
}

Response (200 OK)

json
{
  "user_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "email": "bob@acme.com",
  "role": "admin",
  "updated_at": "2026-02-20T11:00:00Z"
}

Hierarki Role

RoleIzin
owner Kontrol penuh, billing, hapus org, transfer kepemilikan
admin Kelola anggota, aplikasi, pengaturan, kebijakan
member Akses aplikasi, buat resource dalam aplikasi
viewer Akses baca-saja ke aplikasi dan resource

Hapus Anggota

Menghapus anggota dari organisasi. Akun pengguna tidak dihapus, hanya keanggotaannya.

http
DELETE /api/v1/organizations/{id}/members/{user_id}

Response (200 OK)

json
{
  "user_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "removed_at": "2026-02-20T12:00:00Z"
}

Peringatan

Anda tidak dapat menghapus owner organisasi. Transfer kepemilikan terlebih dahulu menggunakan alur transfer kepemilikan terpisah.

Kebijakan Organisasi

Kebijakan memungkinkan organisasi Business+ untuk menerapkan persyaratan keamanan di semua anggota. Ini mengontrol kekuatan password, MFA, perilaku sesi, dan pembatasan IP.

Fitur Business+

Kebijakan organisasi tersedia di paket Business dan Enterprise. Paket Free dan Starter mendapatkan response 403.

Lihat Kebijakan

http
GET /api/v1/organizations/{id}/policies

Response (200 OK)

json
{
  "organization_id": "550e8400-e29b-41d4-a716-446655440000",
  "password_policy": {
    "min_length": 12,
    "require_uppercase": true,
    "require_lowercase": true,
    "require_numbers": true,
    "require_special_chars": true,
    "max_age_days": 90,
    "prevent_reuse_count": 5
  },
  "mfa_policy": {
    "required": true,
    "allowed_methods": ["totp", "webauthn"],
    "grace_period_hours": 48
  },
  "session_policy": {
    "max_session_duration_hours": 24,
    "idle_timeout_minutes": 30,
    "max_concurrent_sessions": 5
  },
  "ip_allowlist": {
    "enabled": false,
    "allowed_ips": []
  },
  "updated_at": "2026-02-15T09:00:00Z"
}

Perbarui Kebijakan

Mengganti seluruh konfigurasi kebijakan. Sertakan semua bagian kebijakan dalam request.

http
PUT /api/v1/organizations/{id}/policies
Content-Type: application/json

Request Body

json
{
  "password_policy": {
    "min_length": 14,
    "require_uppercase": true,
    "require_lowercase": true,
    "require_numbers": true,
    "require_special_chars": true,
    "max_age_days": 60,
    "prevent_reuse_count": 10
  },
  "mfa_policy": {
    "required": true,
    "allowed_methods": ["totp", "webauthn"],
    "grace_period_hours": 24
  },
  "session_policy": {
    "max_session_duration_hours": 12,
    "idle_timeout_minutes": 15,
    "max_concurrent_sessions": 3
  },
  "ip_allowlist": {
    "enabled": true,
    "allowed_ips": ["203.0.113.0/24", "198.51.100.42"]
  }
}

Field Kebijakan

BagianFieldTipeDeskripsi
password_policy min_length int Panjang minimum password (8-128)
require_uppercase boolean Wajib minimal satu huruf besar
require_lowercase boolean Wajib minimal satu huruf kecil
require_numbers boolean Wajib minimal satu digit
require_special_chars boolean Wajib minimal satu karakter khusus
max_age_days int Paksa reset password setelah N hari (0 = nonaktif)
prevent_reuse_count int Jumlah password sebelumnya yang diblokir (0-24)
mfa_policy required boolean Wajibkan MFA untuk semua anggota
allowed_methods string[] Metode MFA yang diizinkan: totp, webauthn
grace_period_hours int Jam sebelum MFA diberlakukan setelah perubahan kebijakan
session_policy max_session_duration_hours int Masa hidup sesi absolut (1-720)
idle_timeout_minutes int Timeout tidak aktif (5-1440)
max_concurrent_sessions int Sesi aktif maksimum per pengguna (1-100)
ip_allowlist enabled boolean Aktifkan pembatasan IP
allowed_ips string[] IP atau range CIDR yang diizinkan

Response (200 OK)

Mengembalikan objek kebijakan yang diperbarui secara lengkap (bentuk sama dengan response GET).

Branding Organisasi

Kustomisasi tampilan dan nuansa halaman autentikasi dan email untuk organisasi Anda (white-label). Tersedia di paket Business+.

Fitur Business+

Kustomisasi branding tersedia di paket Business dan Enterprise.

Lihat Branding

http
GET /api/v1/organizations/{id}/branding

Response (200 OK)

json
{
  "organization_id": "550e8400-e29b-41d4-a716-446655440000",
  "logo_url": "https://cdn.arsaka.io/orgs/acme/logo.png",
  "favicon_url": "https://cdn.arsaka.io/orgs/acme/favicon.ico",
  "primary_color": "#2563EB",
  "accent_color": "#7C3AED",
  "custom_login": {
    "title": "Acme Corp Portal",
    "subtitle": "Sign in to your workspace",
    "background_url": "https://cdn.arsaka.io/orgs/acme/bg.jpg"
  },
  "email_branding": {
    "from_name": "Acme Corp",
    "reply_to": "support@acme.com",
    "footer_text": "Acme Corp, 123 Main St, Jakarta"
  },
  "updated_at": "2026-02-18T16:00:00Z"
}

Perbarui Branding

http
PUT /api/v1/organizations/{id}/branding
Content-Type: application/json

Request Body

json
{
  "logo_url": "https://cdn.arsaka.io/orgs/acme/logo-v2.png",
  "primary_color": "#1D4ED8",
  "accent_color": "#6D28D9",
  "custom_login": {
    "title": "Welcome to Acme",
    "subtitle": "Enterprise workspace login",
    "background_url": null
  },
  "email_branding": {
    "from_name": "Acme Corporation",
    "reply_to": "noreply@acme.com",
    "footer_text": "Acme Corporation, Jakarta, Indonesia"
  }
}

Field Branding

FieldTipeDeskripsi
logo_url string URL logo organisasi (PNG/SVG, maks 2 MB)
favicon_url string URL favicon (ICO/PNG, maks 256 KB)
primary_color string Warna brand utama (hex, contoh #2563EB)
accent_color string Warna brand aksen (hex)
custom_login.title string Judul halaman login
custom_login.subtitle string Subjudul halaman login
custom_login.background_url string|null URL gambar latar halaman login (null untuk menghapus)
email_branding.from_name string Nama tampilan di email keluar
email_branding.reply_to string Alamat email reply-to
email_branding.footer_text string Teks footer di email transaksional

Response (200 OK)

Mengembalikan objek branding yang diperbarui secara lengkap (bentuk sama dengan response GET).

Konfigurasi SSO

Konfigurasi Single Sign-On berbasis SAML untuk organisasi Anda. Saat SSO diaktifkan, anggota melakukan autentikasi melalui identity provider (IdP) Anda, bukan kredensial PUGUH.

Fitur Business+

SSO tersedia di paket Business dan Enterprise. Mendukung SAML 2.0 dengan IdP yang kompatibel (Okta, Azure AD, Google Workspace, dll.).

Buat Konfigurasi SSO

http
POST /api/v1/sso/configurations
Content-Type: application/json

Request Body

json
{
  "organization_id": "550e8400-e29b-41d4-a716-446655440000",
  "provider": "saml",
  "idp_entity_id": "https://idp.acme.com/metadata",
  "idp_sso_url": "https://idp.acme.com/sso/saml",
  "idp_certificate": "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----",
  "domain_whitelist": ["acme.com", "acme.co.id"],
  "auto_provision": true,
  "default_role": "member"
}

Field Request

FieldTipeWajibDeskripsi
organization_id uuid Ya Organisasi yang akan dikonfigurasi SSO
provider string Ya Tipe provider SSO: saml
idp_entity_id string Ya Entity ID Identity Provider (dari metadata IdP)
idp_sso_url string Ya URL Single Sign-On IdP
idp_certificate string Ya Sertifikat X.509 IdP (format PEM)
domain_whitelist string[] Tidak Domain email yang harus menggunakan SSO
auto_provision boolean Tidak Otomatis buat akun pengguna saat login SSO pertama (default false)
default_role string Tidak Role untuk pengguna yang otomatis dibuat (default member)

Response (201 Created)

json
{
  "organization_id": "550e8400-e29b-41d4-a716-446655440000",
  "provider": "saml",
  "idp_entity_id": "https://idp.acme.com/metadata",
  "idp_sso_url": "https://idp.acme.com/sso/saml",
  "sp_entity_id": "https://api-puguh.arsaka.io/sso/saml/550e8400",
  "sp_acs_url": "https://api-puguh.arsaka.io/sso/saml/550e8400/acs",
  "domain_whitelist": ["acme.com", "acme.co.id"],
  "auto_provision": true,
  "default_role": "member",
  "is_active": true,
  "created_at": "2026-02-20T10:00:00Z"
}

Tip

Setelah membuat konfigurasi SSO, gunakan sp_entity_id dan sp_acs_url yang dikembalikan untuk mengkonfigurasi Service Provider di IdP Anda.

Lihat Konfigurasi SSO

http
GET /api/v1/sso/configurations/{org_id}

Response (200 OK)

json
{
  "organization_id": "550e8400-e29b-41d4-a716-446655440000",
  "provider": "saml",
  "idp_entity_id": "https://idp.acme.com/metadata",
  "idp_sso_url": "https://idp.acme.com/sso/saml",
  "sp_entity_id": "https://api-puguh.arsaka.io/sso/saml/550e8400",
  "sp_acs_url": "https://api-puguh.arsaka.io/sso/saml/550e8400/acs",
  "domain_whitelist": ["acme.com", "acme.co.id"],
  "auto_provision": true,
  "default_role": "member",
  "is_active": true,
  "created_at": "2026-02-20T10:00:00Z",
  "updated_at": "2026-02-20T10:00:00Z"
}

Perbarui Konfigurasi SSO

http
PUT /api/v1/sso/configurations/{org_id}
Content-Type: application/json

Request Body

json
{
  "idp_sso_url": "https://idp.acme.com/sso/saml/v2",
  "idp_certificate": "-----BEGIN CERTIFICATE-----\nNEWC...\n-----END CERTIFICATE-----",
  "domain_whitelist": ["acme.com"],
  "auto_provision": false
}

Response (200 OK)

Mengembalikan objek konfigurasi SSO yang diperbarui secara lengkap (bentuk sama dengan response GET).

Response Error

Semua error mengembalikan kode status HTTP yang sesuai dengan body JSON berisi field detail. Tidak ada wrapper {success, error}.

400 Bad Request

Body request atau parameter tidak valid:

json
{
  "detail": "Validation error: name must be between 2 and 100 characters"
}

401 Unauthorized

Autentikasi tidak ada atau tidak valid:

json
{
  "detail": "Invalid or expired token"
}

403 Forbidden

Izin tidak memadai atau pembatasan paket:

json
{
  "detail": "Organization policies require Business plan or higher"
}

Atau role tidak memadai:

json
{
  "detail": "Only organization owner or admin can invite members"
}

404 Not Found

Organisasi atau anggota tidak ditemukan:

json
{
  "detail": "Organization not found"
}

409 Conflict

Resource duplikat:

json
{
  "detail": "Organization with slug 'acme-corp' already exists"
}

Atau undangan duplikat:

json
{
  "detail": "User bob@acme.com is already a member of this organization"
}

422 Unprocessable Entity

Request tidak valid secara semantik:

json
{
  "detail": "Cannot remove the last owner from the organization"
}

429 Too Many Requests

Rate limit terlampaui:

json
{
  "detail": "Rate limit exceeded. Retry after 60 seconds"
}

Terkait