Python SDK
PUGUH Python SDK menyediakan client async-first untuk mengintegrasikan autentikasi, organisasi, aplikasi, dan billing ke layanan backend Python Anda. SDK ini mendukung pola autentikasi user-session dan service-to-service.
Instalasi
pip install puguh-sdk Mulai Cepat
Konteks User (Frontend / Sesi User)
Gunakan access token yang diperoleh dari login user untuk membuat request atas nama user:
from puguh_sdk import PuguhClient
async with PuguhClient(
base_url="https://api-puguh.arsaka.io",
access_token="user_jwt_token"
) as client:
# List organizations the user belongs to
orgs = await client.organizations.list()
for org in orgs:
print(f"{org.name} ({org.slug})") Konteks Service (Backend / Service-to-Service)
Gunakan API key untuk layanan backend yang perlu memanggil PUGUH tanpa sesi user:
from puguh_sdk import PuguhClient
async with PuguhClient(
base_url="https://api-puguh.arsaka.io",
api_key="pk_live_xxxxxxxxxxxx"
) as client:
# Fetch available billing plans
plans = await client.billing.get_plans()
for plan in plans:
print(f"{plan.name}: {plan.price}/mo") Dua Mode Autentikasi
Gunakan access_token saat bertindak atas nama user yang sudah login (contoh: di route API yang menerima JWT dari frontend). Gunakan api_key untuk layanan backend, cron job, atau skrip admin yang beroperasi tanpa sesi user.
Modul Layanan
SDK menyediakan empat modul layanan, masing-masing dapat diakses sebagai properti pada instance client.
Auth (client.auth)
Menangani autentikasi user, siklus hidup token, MFA, dan magic link.
# Login — returns access_token and refresh_token
tokens = await client.auth.login(
email="user@example.com",
password="secure_password"
)
print(tokens.access_token)
# Register a new user
user = await client.auth.register(
email="new@example.com",
password="secure_password",
full_name="Jane Doe"
)
print(user.user_id)
# Refresh an expired access token
new_tokens = await client.auth.refresh_token(
refresh_token=tokens.refresh_token
)
# Validate a token and get user context
user_ctx = await client.auth.validate_token(token=tokens.access_token)
print(user_ctx.email, user_ctx.roles)
# Magic link authentication
await client.auth.request_magic_link(email="user@example.com")
tokens = await client.auth.verify_magic_link(token="ml_token_from_email")
# Multi-Factor Authentication
setup = await client.auth.setup_mfa()
print(setup.qr_code_url) # Show QR to user
await client.auth.confirm_mfa(code="123456")
await client.auth.disable_mfa() Catatan
Tidak ada metode get_me(). Informasi user tersedia dari response login atau dengan mendekode JWT claims secara lokal menggunakan endpoint PUGUH JWKS.
Organizations (client.organizations)
Kelola organisasi dan anggotanya.
# List organizations
orgs = await client.organizations.list()
# Create a new organization
org = await client.organizations.create(
name="Acme Corp",
slug="acme-corp"
)
# Get organization details
org = await client.organizations.get(org_id="org-uuid")
# Update organization
await client.organizations.update(
org_id="org-uuid",
name="Acme Corporation"
)
# Delete organization
await client.organizations.delete(org_id="org-uuid")
# Member management
members = await client.organizations.list_members(org_id="org-uuid")
await client.organizations.invite_member(
org_id="org-uuid",
email="colleague@example.com",
role="member"
)
await client.organizations.update_member_role(
org_id="org-uuid",
user_id="user-uuid",
role="admin"
)
await client.organizations.remove_member(
org_id="org-uuid",
user_id="user-uuid"
) Applications (client.applications)
Kelola aplikasi dalam organisasi.
# List applications in an organization
apps = await client.applications.list(org_id="org-uuid")
# Create an application
app = await client.applications.create(
org_id="org-uuid",
name="My SaaS App",
slug="my-saas-app"
)
# Get application details
app = await client.applications.get(app_id="app-uuid")
# Update application
await client.applications.update(
app_id="app-uuid",
name="My SaaS App v2"
)
# Delete application
await client.applications.delete(app_id="app-uuid")
# Application member management
members = await client.applications.list_members(app_id="app-uuid")
await client.applications.add_member(
app_id="app-uuid",
user_id="user-uuid",
role="member"
) Billing (client.billing)
Kelola subscription, paket, invoice, dan metering penggunaan.
# List available plans
plans = await client.billing.get_plans()
for plan in plans:
print(f"{plan.name}: {plan.price}")
# Get a specific plan
plan = await client.billing.get_plan(plan_id="plan-uuid")
# Get current subscription for an organization
sub = await client.billing.get_subscription(org_id="org-uuid")
print(f"Plan: {sub.plan_name}, Status: {sub.status}")
# Create a new subscription
sub = await client.billing.create_subscription(
org_id="org-uuid",
plan_id="plan-uuid"
)
# Upgrade to a different plan
await client.billing.upgrade(
org_id="org-uuid",
plan_id="new-plan-uuid"
)
# Cancel subscription
await client.billing.cancel(org_id="org-uuid")
# Invoices and usage
invoices = await client.billing.get_invoices(org_id="org-uuid")
usage = await client.billing.get_usage(org_id="org-uuid") Manajemen Konteks
Atur konteks organisasi dan aplikasi agar tidak perlu memasukkan ID di setiap panggilan. Setelah diatur, konteks dikirim otomatis dengan semua request berikutnya.
from puguh_sdk import PuguhClient
async with PuguhClient(
base_url="https://api-puguh.arsaka.io",
api_key="pk_live_xxxxxxxxxxxx"
) as client:
# Set organization context
client.set_organization_context("org-uuid")
# Set application context
client.set_application_context("app-uuid")
# Now calls automatically include these IDs
members = await client.organizations.list_members()
# Clear context when switching
client.clear_context() Penanganan Error
SDK melempar exception bertipe untuk skenario error yang berbeda. Selalu bungkus panggilan SDK dalam blok try/except untuk kode produksi.
from puguh_sdk import PuguhClient
from puguh_sdk.exceptions import (
PuguhError,
AuthError,
RateLimitError,
NetworkError,
)
async with PuguhClient(
base_url="https://api-puguh.arsaka.io",
access_token="user_jwt_token"
) as client:
try:
orgs = await client.organizations.list()
except AuthError as e:
# Token expired or invalid — redirect to login
print(f"Authentication failed: {e}")
except RateLimitError as e:
# Too many requests — back off and retry
print(f"Rate limited. Retry after {e.retry_after}s")
except NetworkError as e:
# Connection failed — check network or API status
print(f"Network error: {e}")
except PuguhError as e:
# Catch-all for any other PUGUH API error
print(f"API error {e.status_code}: {e.message}") Hierarki Exception
| Exception | Kapan | Tindakan Tipikal |
|---|---|---|
AuthError | 401 Unauthorized atau token tidak valid | Refresh token atau redirect ke login |
RateLimitError | 429 Too Many Requests | Tunggu retry_after detik, lalu coba lagi |
NetworkError | Timeout koneksi atau kegagalan DNS | Coba ulang dengan backoff atau alert ops |
PuguhError | Response 4xx/5xx lainnya | Log dan tangani berdasarkan kode status |
Environment Variables
Cara yang direkomendasikan untuk mengkonfigurasi SDK di produksi:
# .env
PUGUH_BASE_URL=https://api-puguh.arsaka.io
PUGUH_API_KEY=pk_live_xxxxxxxxxxxx import os
from puguh_sdk import PuguhClient
async with PuguhClient(
base_url=os.environ["PUGUH_BASE_URL"],
api_key=os.environ["PUGUH_API_KEY"],
) as client:
plans = await client.billing.get_plans() Praktik Terbaik
1. Gunakan Environment Variables untuk Kredensial
Jangan pernah hardcode API key atau token di source code:
# Bad — credentials in source code
client = PuguhClient(api_key="pk_live_abc123")
# Good — credentials from environment
client = PuguhClient(api_key=os.environ["PUGUH_API_KEY"]) 2. Selalu Gunakan Async Context Manager
Context manager memastikan koneksi HTTP ditutup dengan benar:
# Bad — connection may leak
client = PuguhClient(base_url="...", api_key="...")
orgs = await client.organizations.list()
# forgot to close
# Good — auto-cleanup on exit
async with PuguhClient(base_url="...", api_key="...") as client:
orgs = await client.organizations.list()
# connection closed automatically 3. Tangani Error di Level yang Tepat
Tangkap exception spesifik dekat dengan call site, dan biarkan error tak terduga naik ke atas:
async def get_user_orgs(access_token: str) -> list:
async with PuguhClient(
base_url=os.environ["PUGUH_BASE_URL"],
access_token=access_token,
) as client:
try:
return await client.organizations.list()
except AuthError:
# Expected: token expired
raise HTTPException(status_code=401, detail="Session expired")
# Let NetworkError, PuguhError bubble up to global handler 4. Gunakan Ulang Instance Client
Untuk layanan yang berjalan lama, buat client sekali dan gunakan ulang di seluruh request:
# In your FastAPI app
from contextlib import asynccontextmanager
from puguh_sdk import PuguhClient
puguh_client: PuguhClient | None = None
@asynccontextmanager
async def lifespan(app):
global puguh_client
puguh_client = PuguhClient(
base_url=os.environ["PUGUH_BASE_URL"],
api_key=os.environ["PUGUH_API_KEY"],
)
await puguh_client.__aenter__()
yield
await puguh_client.__aexit__(None, None, None)
app = FastAPI(lifespan=lifespan)
@app.get("/plans")
async def list_plans():
return await puguh_client.billing.get_plans() Persyaratan Versi Python
PUGUH Python SDK memerlukan Python 3.11+ dan menggunakan asyncio secara native. Semua metode bersifat async dan harus di-await.