Metadata-Version: 2.4
Name: virturing
Version: 0.4.0
Summary: Server-side Python SDK for the Virturing Voice API
Author-email: Virturing <admin@virturing.ai>
License-Expression: MIT
Project-URL: Homepage, https://virturing.ai
Project-URL: Repository, https://github.com/Virturing/virturing_app
Project-URL: Issues, https://github.com/Virturing/virturing_app/issues
Keywords: virturing,voice-ai,telephony,realtime,websocket
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
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: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Virturing Python SDK

Dependency-free synchronous and asynchronous clients for Python 3.10+.

```python
import os
from virturing import Virturing

voice = Virturing(os.environ["VIRTURING_API_KEY"])
call = voice.create_call(
    agent_id="agent_uuid",
    phone_number_id="number_uuid",
    to_number="+94771234567",
    channel="ai",
    metadata={"employee_id": "EMP-1042", "shift": "morning"},
)
```

Use an ephemeral dynamic agent for a one-off task created by trusted server
code:

```python
call = voice.create_dynamic_call(
    phone_number_id="number_uuid",  # Or connector_id for your own carrier.
    to_number="+94771234567",
    dynamic_agent={
        "name": "Attendance confirmation",
        "instructions": "Confirm attendance. Never infer an answer.",
        "first_message": "Hello, I am calling to confirm your attendance tomorrow.",
        "output_fields": [{
            "extractionType": "ai",
            "name": "attending",
            "description": "Whether the recipient confirms attendance.",
            "resultFormat": "boolean",
            "exampleOutput": "true",
            "required": True,
            "confirmation": "explicit",
        }],
    },
    metadata={"employee_id": "EMP-1042"},
    idempotency_key="attendance-EMP-1042",
)
```

Virturing validates and freezes the inline configuration with the call. It is
auditable and safe to retry but does not become a reusable portal agent. Dynamic
payloads also work in batches and scheduled calls.

For a monitoring alert, create a one-way alert agent in the portal and send the
exact text from trusted server code:

```python
alert = voice.create_alert_call(
    agent_id="alert_agent_uuid",
    phone_number_id="number_uuid",
    to_number="+94771234567",
    message="Production alert. Checkout latency has exceeded two seconds.",
    metadata={"incident_id": "INC-2042"},
    idempotency_key="incident-INC-2042",
)
```

Virturing speaks the message with the alert agent's configured voice and hangs
up. No STT, LLM, tools, or conversational workflow is started. Carrier usage
and generated TTS audio remain prepaid and metered.

To keep an existing Twilio number and carrier account, point its incoming-call webhook to the connector URL shown in Virturing. Start outgoing calls through that connector with:

    call = voice.create_twilio_call(
        connector_id="connector_uuid",
        agent_id="agent_uuid",
        to_number="+94771234567",
        metadata={"customer_ref": "CUST-1042"},
        idempotency_key="customer-call-CUST-1042",
    )

Twilio continues to bill the carrier leg; Virturing deducts only metered AI/platform usage from the USD wallet.

To use a Virturing number with your own AI or media server, register a WSS endpoint and start a programmable call:

    created = voice.create_media_endpoint(
        name="My voice service",
        url="wss://voice.example.com/virturing/media",
    )
    # Store created["signing_secret"] once in your server-side secret manager.
    voice.create_programmable_call(
        phone_number_id="number_uuid",
        media_endpoint_id=created["endpoint"]["id"],
        to_number="+94771234567",
    )

`verify_media_stream_signature` authenticates the WSS opening handshake. The stream uses bidirectional PCM16 mono audio at 8 kHz. See `docs/programmable-media.md` for the complete contract and customer-hosted Python and Node examples.

The client automatically uses idempotency keys and retries only safe operations. Keep the API key in server-side secrets. `verify_webhook_signature` validates the exact raw request body before JSON parsing.

Use `Virturing(client_id=..., client_secret=..., scopes=[...])` for OAuth client credentials. Access tokens are cached and refreshed automatically. `create_media_session(...)` creates a metered realtime voice session for a web, desktop, or mobile client.
