VlunaAI Python SDK for billing and usage gate APIs
Project description
vlunaai
Official async Python SDK for VlunaAI Billing and Usage Gate APIs.
The SDK bundles:
- A shared async HTTP client (httpx) with retries + idempotency keys
- Authentication helpers (Service Key signing, Bearer token via context)
- Generated Pydantic v2 models
Documentation:
https://docs.vluna.ai/docs/adapters/sdk
Installation
pip install vlunaai
Requires Python >= 3.8.
Package contents
- Async service client for server-to-server (
/mgt/v1) APIs - Async bearer client for end-user (
/api/v1) APIs - Service Key authentication helpers
- Generated Pydantic v2 models and typed request/response surfaces
Quickstart (Service Key, server-to-server)
Configure Service Key auth (S2S):
- If you use Vluna Cloud (hosted), get these values from the dashboard.
- If you self-host, provision them using your Vluna deployment and service-key setup flow.
Set them in the environment where you run your sdk integration:
export VLUNA_REALM_ID='...'
export VLUNA_SERVICE_KEY_ID='pk-...'
export VLUNA_SERVICE_KEY_SECRET='...'
Use ServiceClient for service-to-service calls to the management surface (/mgt/v1).
import asyncio
import os
from vlunaai import (
VlunaAIConfig,
RequestContext,
ServiceClientOptions,
ServiceKeyCredentials,
create_service_client,
)
def env(name: str) -> str:
value = os.environ.get(name)
if not value:
raise RuntimeError(f'Missing environment variable: {name}')
return value
async def main() -> None:
service_base_url = os.environ.get('VLUNA_SERVICE_BASE_URL', 'https://us-central1.api.vluna.ai/mgt/v1')
realm_id = env('VLUNA_REALM_ID')
principal_id = YOUR_PRINCIPAL_ID # your customer's organization id, team id, user id, etc...
user_id = YOUR_USER_ID
client = create_service_client(
ServiceClientOptions(
config=VlunaAIConfig(
base_url=service_base_url,
realm_id=realm_id,
),
service_key=ServiceKeyCredentials(
key_id=env('VLUNA_SERVICE_KEY_ID'),
secret=env('VLUNA_SERVICE_KEY_SECRET'), # base64-encoded secret
),
)
)
try:
ctx = RequestContext(principal_id=principal_id)
feature_code = 'openai.gpt5.2'
# 1) authorize: ask Vluna for a lease token before performing work
authz = await client.gate_authorize(body={'feature_code': feature_code, 'feature_family_code': 'llm.premium'}, context=ctx)
if not authz.data:
raise RuntimeError('gate_authorize returned no data')
lease_token = authz.data.lease_token
# ...perform the protected work...
# 2) commit: report usage once the work completes
commit = await client.gate_commit(
body={'lease_token': lease_token, 'feature_code': feature_code, 'quantity_minor': '12345'},
context=ctx,
)
print(commit.model_dump())
# 3) billing helpers
balance = await client.get_credit_balance(context=ctx)
print(balance.model_dump())
# 4) token issuance: your backend can return this access_token to your frontend/mobile app for bearer-auth calls.
token_envelope = await client.issue_platform_token(
body={
'principal_id': principal_id,
'user_id': user_id,
'scopes': ['checkout', 'portal'],
'session_ttl_sec': 900,
},
context=ctx,
)
if not token_envelope.data:
raise RuntimeError('issue_platform_token returned no data')
access_token = token_envelope.data.access_token
print(access_token)
finally:
await client.close()
asyncio.run(main())
Quickstart (Bearer token, end-user calls)
Use BearerClient for user/bearer-auth calls to the public surface (/api/v1).
In a typical setup, your frontend/mobile app fetches an platform access token from your backend (issued via the S2S flow above), then uses it as a bearer token for end-user calls.
import asyncio
import os
from vlunaai import (
VlunaAIConfig,
BearerClientOptions,
RequestContext,
create_bearer_client,
)
def env(name: str) -> str:
value = os.environ.get(name)
if not value:
raise RuntimeError(f'Missing environment variable: {name}')
return value
async def main() -> None:
bearer_base_url = os.environ.get('VLUNA_BEARER_BASE_URL', 'https://us-central1.api.vluna.ai/api/v1')
realm_id = env('VLUNA_REALM_ID')
billing_account_id = env('VLUNA_BILLING_ACCOUNT_ID')
access_token = env('VLUNA_ACCESS_TOKEN') # obtain from your backend (see ServiceClient.issue_platform_token)
client = create_bearer_client(
BearerClientOptions(
config=VlunaAIConfig(
base_url=bearer_base_url,
realm_id=realm_id,
)
)
)
try:
ctx = RequestContext(access_token=access_token, billing_account_id=billing_account_id)
products = await client.list_catalog_products(context=ctx)
print(products)
finally:
await client.close()
asyncio.run(main())
Key concepts
realm_id
- Required in
VlunaAIConfig. - Identifies the Realm (business project) and is sent as
X-Realm-Idon every request.
billing_account_id
- Account-scoped endpoints require
billing_account_id(sent asX-Billing-Account-ID). - Pass it via
RequestContext(billing_account_id=...).
principal_id
- Your business identifier that maps 1:1 to a billing account (for example
user_id,org_id,team_id). - Pass it via
RequestContext(principal_id=...)when the endpoint expects it (for example token issuance flows).
More details:
https://docs.vluna.ai/docs/adapters/sdk
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vlunaai-0.1.2.tar.gz.
File metadata
- Download URL: vlunaai-0.1.2.tar.gz
- Upload date:
- Size: 77.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
edc3071863b96a9579d6a0ff6d88edb40e8084d1d6567b48bae44da062e7aad4
|
|
| MD5 |
6a30fa51ab9c32ac0d644779c225e797
|
|
| BLAKE2b-256 |
965283606cc6b3c0288b3799241e0cc68ada2e145d50dec0ed999138fb368c6a
|
File details
Details for the file vlunaai-0.1.2-py3-none-any.whl.
File metadata
- Download URL: vlunaai-0.1.2-py3-none-any.whl
- Upload date:
- Size: 35.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
049b469a80f286c651c744d3105820a08bc634e71872ce8db854d614c23b505c
|
|
| MD5 |
921f18a2f6a9ea311b227cadc1decd8a
|
|
| BLAKE2b-256 |
5cb5adaf9f927bf4c13ce33b66d1098190be5499dcece6ab6c54ce138d88ffc9
|