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.3.0.tar.gz (19.1 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.3.0-py3-none-any.whl (17.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: conxa_sdk-1.3.0.tar.gz
  • Upload date:
  • Size: 19.1 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.3.0.tar.gz
Algorithm Hash digest
SHA256 ce7de1d77c36b6a4420fbcf2919b85db4e0bfa2c045bd9622920999750082706
MD5 64efdf4870f8f05722f28321fbd71861
BLAKE2b-256 80ffc806b7a01f3cadaf8d4ffc833da8b8ebdc14c0c0d7c008f40c06a93675ab

See more details on using hashes here.

File details

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

File metadata

  • Download URL: conxa_sdk-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 17.2 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.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 95eb5f555f2fec3e6d27809627e324c04cd6e2d90ae2a00cb65a58d5127f61ee
MD5 2e02e662ed2ca7b9bca7630a6fab082c
BLAKE2b-256 e2ee297abe31d52e9de33d87a23ed598a1f1a3bb67a3439e99b5aca921649b2d

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