Metadata-Version: 2.4
Name: vlunaai
Version: 0.1.4
Summary: VlunaAI Python SDK for billing and usage gate APIs
Project-URL: Homepage, https://vluna.ai
Project-URL: Documentation, https://docs.vluna.ai/docs/adapters/sdk
Project-URL: Repository, https://github.com/lapbay/vluna
Project-URL: Issues, https://github.com/lapbay/vluna/issues
Author: VlunaAI
License: MIT License
        
        Copyright (c) 2026 VlunaAI
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: agentic,ai,ai agent,billing,metering,payments,sdk,usage-gate,vlunaai
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.8
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.6
Requires-Dist: python-dateutil>=2.8.2
Requires-Dist: typing-extensions>=4.7
Requires-Dist: urllib3<3.0,>=2.1
Provides-Extra: dev
Requires-Dist: mypy>=1.9; extra == 'dev'
Requires-Dist: pytest>=8.1; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.3; extra == 'dev'
Description-Content-Type: text/markdown

# 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

```bash
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:

```bash
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`).

```python
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/team/workspace id
  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, user_id=user_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.

```python
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')
  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)
    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-Id` on every request.

`billing_account_id`
- Payor/account-scoped endpoints may use `billing_account_id` (sent as `X-Billing-Account-Id`) or `principal_id`.
- Runtime metering and gate endpoints should not use `billing_account_id` as the user subject.

`principal_id`
- Your business identifier for the payor account (for example `org_id`, `team_id`, or `workspace_id`).
- For service-key runtime calls, pass it with `user_id` via `RequestContext(principal_id=..., user_id=...)`.

`user_id`
- Your business identifier for the runtime user inside the billing account.
- Required with `principal_id` for service-key gate, wallet, budget, and event calls.

More details:
- `https://docs.vluna.ai/docs/adapters/sdk`
