Skip to main content

Python SDK for integrating CONXA Wallet payments into AI services

Project description

CONXA Python SDK

Official Python SDK for integrating CONXA Wallet payments into AI services.

Overview

CONXA is a universal wallet for AI services. This SDK enables AI providers (ChatGPT, Claude, etc.) to:

  1. Generate QR codes for users to connect their CONXA wallet
  2. Detect connections when users scan and approve
  3. Charge users for AI usage (pay-per-token)
  4. Check balances and manage sessions

Installation

# Basic installation
pip install conxa-sdk

# With QR code generation support
pip install conxa-sdk[qr]

# From source
pip install .

Quick Start

from conxa import CONXAClient

# Initialize with your API key
client = CONXAClient(
    api_key="pk_live_your_api_key",
    provider_id="your_provider_id",
)

# 1. Generate QR code for user to scan
qr = client.create_payment_qr(
    provider_username="user@example.com",
    expires_in=10  # Optional: QR expires after 10 seconds
)
print(f"Show this QR to user: {qr.qr_base64}")

# 2. Wait for user to connect (or poll manually)
session = client.wait_for_connection(
    provider_username="user@example.com",
    timeout=120,  # Wait up to 2 minutes
    qr_data=qr,  # Pass QR data to check expiration
)
print(f"User connected! Token: {session.session_token}")

# 3. Charge for AI usage
result = client.charge(
    session_token=session.session_token,
    model_name="gpt-4",
    input_tokens=1000,
    output_tokens=500,
)

if result.approved:
    print(f"Charged! New balance: {result.new_balance} tokens")
else:
    print(f"Failed: {result.error}")

Integration Flow

┌─────────────────────────────────────────────────────────────────┐
│                        YOUR AI SERVICE                          │
│                                                                 │
│  1. User visits your website                                    │
│     │                                                           │
│     ▼                                                           │
│  2. Generate QR: client.create_payment_qr(username, expires_in=10) │
│     │                                                           │
│     ▼                                                           │
│  3. Display QR code to user (expires after 10 seconds)         │
│     │                                                           │
│     │    ┌─────────────────────────────────┐                   │
│     │    │      CONXA Mobile App           │                   │
│     └───▶│  User scans QR & approves       │                   │
│          │  Connection established!         │                   │
│          └─────────────────────────────────┘                   │
│     │                                                           │
│     ▼                                                           │
│  4. Detect connection: client.get_session_status(username, qr_data=qr) │
│     │                                                           │
│     ▼                                                           │
│  5. For each AI request:                                        │
│     result = client.charge(session_token, model, tokens)        │
│     │                                                           │
│     ▼                                                           │
│  6. Tokens deducted from user's CONXA wallet                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

API Reference

CONXAClient

Main client class for interacting with CONXA API.

client = CONXAClient(
    api_key="pk_live_xxx",           # Required: Your API key
    provider_id="your_provider_id",   # Required: Your provider ID
    base_url="https://api.conxa.in",  # Optional: API base URL
    timeout=30,                       # Optional: Request timeout
    provider_type="api",              # Optional: "api" or "web"
)

Methods

create_payment_qr(provider_username, limit=None, size=300, expires_in=None)

Generate a QR code for user to scan and connect.

qr = client.create_payment_qr(
    provider_username="user@example.com",
    limit=50000,      # Optional: spending limit in tokens
    size=300,         # Optional: image size in pixels
    expires_in=10,    # Optional: QR expires after N seconds (default: None)
)

# Returns QRCodeData:
# - qr.qr_data: JSON string to encode
# - qr.qr_image: PIL Image object
# - qr.qr_base64: Base64 PNG for HTML <img> tag
# - qr.created_at: Timestamp when QR was created
# - qr.expires_at: Timestamp when QR expires (if expires_in is set)
# - qr.is_expired(): Method to check if QR has expired

QR Code Expiration:

If expires_in is set, the QR code will automatically expire after the specified number of seconds. This is useful for security and ensuring users generate fresh QR codes:

# Generate QR that expires after 10 seconds
qr = client.create_payment_qr(
    provider_username="user@example.com",
    expires_in=10
)

# Check if QR has expired
if qr.is_expired():
    print("QR code expired! Generate a new one.")
    qr = client.create_payment_qr(provider_username="user@example.com", expires_in=10)

get_session_status(provider_username, retry_on_rate_limit=True, max_retries=3, qr_data=None)

Check if user has connected their wallet. Automatically handles rate limiting with exponential backoff.

qr = client.create_payment_qr("user@example.com", expires_in=10)
status = client.get_session_status(
    "user@example.com",
    qr_data=qr,  # Optional: Check if QR has expired
    retry_on_rate_limit=True,  # Auto-retry on rate limits
    max_retries=3,  # Max retry attempts
)

# Returns SessionStatus:
# - status.status: "pending", "active", "expired", "not_found"
# - status.session_token: Token for charges (if active)
# - status.expires_at: Session expiration time
# - status.is_active: Boolean helper

# Raises SessionExpiredError if QR code has expired

Rate Limit Handling:

The SDK automatically retries on rate limit errors (429) with exponential backoff. If qr_data is provided and the QR has expired, it will raise SessionExpiredError instead of polling.

wait_for_connection(provider_username, timeout=120, poll_interval=2, on_pending=None, rate_limit_timeout=10, qr_data=None)

Block until user connects or timeout. Automatically handles rate limiting and QR expiration.

qr = client.create_payment_qr("user@example.com", expires_in=10)

session = client.wait_for_connection(
    provider_username="user@example.com",
    timeout=120,              # Maximum wait time in seconds
    poll_interval=2,         # Time between status checks
    on_pending=lambda s: print("Waiting..."),  # Callback on each poll
    rate_limit_timeout=10,   # Close QR after N seconds of rate limiting
    qr_data=qr,             # Optional: Check QR expiration
)

# Raises:
# - ConnectionTimeoutError: If user doesn't connect within timeout
# - SessionExpiredError: If QR expires or rate limited for too long

Features:

  • Automatic retry on rate limit errors with exponential backoff
  • QR expiration checking (if qr_data provided)
  • Rate limit timeout protection (closes QR after extended rate limiting)

charge(session_token, model_name, input_tokens, output_tokens)

Charge user for AI usage.

result = client.charge(
    session_token="ps_xxx",
    model_name="gpt-4",
    input_tokens=1000,
    output_tokens=500,
)

# Returns ChargeResult:
# - result.approved: Boolean
# - result.new_balance: Remaining tokens
# - result.error: Error message (if failed)

get_wallet_balance(wallet_id)

Get wallet token balance (public endpoint).

balance = client.get_wallet_balance("1234567890123456")
# Returns: WalletBalance(wallet_id, tokens)

Exception Handling

from conxa import (
    CONXAError,
    AuthenticationError,
    InsufficientBalanceError,
    SessionExpiredError,
    ConnectionTimeoutError,
    RateLimitError,
)

try:
    # Generate QR with expiration
    qr = client.create_payment_qr("user@example.com", expires_in=10)
    
    # Wait for connection
    session = client.wait_for_connection("user@example.com", qr_data=qr)
    
    # Charge user
    result = client.charge(...)
    
except SessionExpiredError as e:
    print("QR code or session expired - user needs to reconnect")
    # Generate new QR code
    qr = client.create_payment_qr("user@example.com", expires_in=10)
    
except InsufficientBalanceError as e:
    print(f"User has insufficient balance: {e.current_balance} tokens")
    
except RateLimitError as e:
    print(f"Rate limit exceeded. Retry after: {e.retry_after} seconds")
    # SDK automatically retries, but you can handle manually if needed
    
except ConnectionTimeoutError:
    print("User did not connect within timeout period")
    
except AuthenticationError:
    print("Invalid API key")
    
except CONXAError as e:
    print(f"CONXA error: {e}")

Examples

See the examples/ directory for complete integration examples:

  • basic_integration.py - Simple command-line example
  • flask_integration.py - Flask web app with QR display
  • fastapi_integration.py - FastAPI app with WebSocket support

Web Framework Integration

Flask

from flask import Flask, session, jsonify
from conxa import CONXAClient

app = Flask(__name__)
client = CONXAClient(api_key="pk_live_xxx", provider_id="xxx")

@app.route("/connect")
def connect():
    # Generate QR that expires after 10 seconds
    qr = client.create_payment_qr(
        provider_username=session["user_email"],
        expires_in=10
    )
    # Store QR data in session to check expiration
    session["qr_data"] = {
        "created_at": qr.created_at.isoformat() if qr.created_at else None,
        "expires_at": qr.expires_at.isoformat() if qr.expires_at else None,
    }
    return render_template("connect.html", qr_base64=qr.qr_base64)

@app.route("/api/chat", methods=["POST"])
def chat():
    result = client.charge(
        session_token=session["conxa_token"],
        model_name="gpt-4",
        input_tokens=request.json["input_tokens"],
        output_tokens=request.json["output_tokens"],
    )
    if not result.approved:
        return jsonify({"error": "Insufficient balance"}), 402
    # Process AI request...

FastAPI

from fastapi import FastAPI, HTTPException
from conxa import CONXAClient

app = FastAPI()
client = CONXAClient(api_key="pk_live_xxx", provider_id="xxx")

@app.post("/connect")
async def connect(user_id: str):
    # Generate QR that expires after 10 seconds
    qr = client.create_payment_qr(
        provider_username=user_id,
        expires_in=10
    )
    return {
        "qr_base64": qr.qr_base64,
        "expires_at": qr.expires_at.isoformat() if qr.expires_at else None,
    }

@app.post("/chat")
async def chat(user_id: str, message: str, qr_data: dict = None):
    # Check if QR has expired (if provided)
    qr = None
    if qr_data:
        from conxa.models import QRCodeData
        from datetime import datetime
        qr = QRCodeData(
            qr_data="",
            created_at=datetime.fromisoformat(qr_data["created_at"]) if qr_data.get("created_at") else None,
            expires_at=datetime.fromisoformat(qr_data["expires_at"]) if qr_data.get("expires_at") else None,
        )
    
    try:
        status = client.get_session_status(user_id, qr_data=qr)
    except SessionExpiredError:
        raise HTTPException(401, "QR code expired. Please generate a new one.")
    
    if not status.is_active:
        raise HTTPException(401, "User not connected")
    
    result = client.charge(
        session_token=status.session_token,
        model_name="gpt-4",
        input_tokens=len(message) * 4,
        output_tokens=100,
    )
    if not result.approved:
        raise HTTPException(402, "Insufficient balance")
    # Process AI request...

Configuration

Environment Variables

# API Configuration
CONXA_API_KEY=pk_live_your_api_key
CONXA_PROVIDER_ID=your_provider_id
CONXA_API_URL=https://api.conxa.in  # Optional

Using environment variables:

import os
from conxa import CONXAClient

client = CONXAClient(
    api_key=os.getenv("CONXA_API_KEY"),
    provider_id=os.getenv("CONXA_PROVIDER_ID"),
)

Advanced Features

QR Code Expiration

QR codes can be set to expire after a specified duration for security:

# Generate QR that expires after 10 seconds
qr = client.create_payment_qr(
    provider_username="user@example.com",
    expires_in=10
)

# Check expiration status
if qr.is_expired():
    # Generate new QR
    qr = client.create_payment_qr("user@example.com", expires_in=10)

# When checking status, pass QR data to validate expiration
try:
    status = client.get_session_status("user@example.com", qr_data=qr)
except SessionExpiredError:
    print("QR expired - generate a new one")

Rate Limit Handling

The SDK automatically handles rate limiting with exponential backoff:

# Automatic retry on rate limits (default behavior)
status = client.get_session_status(
    "user@example.com",
    retry_on_rate_limit=True,  # Auto-retry (default)
    max_retries=3,              # Max retry attempts
)

# Manual rate limit handling
try:
    status = client.get_session_status("user@example.com", retry_on_rate_limit=False)
except RateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after} seconds")
    time.sleep(e.retry_after or 60)
    status = client.get_session_status("user@example.com")

Best Practices

  1. Always set QR expiration for security:

    qr = client.create_payment_qr(username, expires_in=10)
    
  2. Pass QR data when checking status to validate expiration:

    status = client.get_session_status(username, qr_data=qr)
    
  3. Handle expiration gracefully:

    try:
        session = client.wait_for_connection(username, qr_data=qr)
    except SessionExpiredError:
        # Generate new QR and try again
        qr = client.create_payment_qr(username, expires_in=10)
    
  4. Use rate limit timeout in wait_for_connection:

    session = client.wait_for_connection(
        username,
        rate_limit_timeout=10,  # Close QR after 10s of rate limiting
        qr_data=qr
    )
    

Support

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

conxa_sdk-1.1.0.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

conxa_sdk-1.1.0-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

Details for the file conxa_sdk-1.1.0.tar.gz.

File metadata

  • Download URL: conxa_sdk-1.1.0.tar.gz
  • Upload date:
  • Size: 19.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for conxa_sdk-1.1.0.tar.gz
Algorithm Hash digest
SHA256 57f552bbfbc8cd9665ffc4cc7ac9eb7da4c28c70c632b156205cdaf3e78a22f3
MD5 fe0c08fd8bbbd2e6cac3e622a30dd15c
BLAKE2b-256 8b3ab711a3f517832e4ff1f9011120309bd1ac09cfa23dd3afcafd5a97109786

See more details on using hashes here.

File details

Details for the file conxa_sdk-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: conxa_sdk-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 17.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for conxa_sdk-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8ce207ff63b0c8af768413834d868b39be224a9e37cea2cb19870e0e767f36a5
MD5 9fd3049e54df8a8331bbc02e1ed6554c
BLAKE2b-256 c08177491c050902d0dd753ce6b2aebc533bdd2c4c8fc866aee955abc8998c96

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page