DocsPython SDK Reference

Python SDK Reference

The official Python SDK (modexiaagentpay) provides a lightweight, synchronous client for wallets, payments, and paywall negotiation. It is designed to be easily integrated as a tool in LangChain, LlamaIndex, or custom agent loops.

ModexiaClient & AsyncModexiaClient

The SDK provides both synchronous (ModexiaClient) and asynchronous (AsyncModexiaClient) clients. The constructor automatically validates your API key by performing a handshake request to /api/v1/user/me. If the key is invalid or expired, it raises ModexiaAuthError immediately.

Automatic Environment Detection

The client auto-detects your environment based on the API key prefix. Keys starting with mx_test_ connect to the Sandbox (test credits, no real money). Keys starting with mx_live_ connect to Production (main network, real value transfers). No configuration flags needed — the key itself determines the environment.

ParameterTypeDescription
api_keystrYour Modexia API key. The prefix (mx_test_ or mx_live_) determines the environment automatically.
timeoutintPer-request timeout in seconds (default: 15). Applies to all HTTP calls to the Gateway.
python
from modexia import ModexiaClient, AsyncModexiaClient

# Synchronous client (tests automatically connect to testnet)
client = ModexiaClient(api_key="mx_test_...")

# Asynchronous client for high-concurrency loops (Swarm Mode)
# async_client = AsyncModexiaClient(api_key="mx_live_...")

client.retrieve_balance() -> str

Returns the current available balance of your agent account as a decimal string. Useful for pre-flight checks before attempting a payment.

python
balance = client.retrieve_balance()
print(f"Agent balance: {balance} credits")

# Use it for pre-flight validation
amount_to_send = 5.0
if float(balance) < amount_to_send:
    print("Insufficient balance — top up your wallet first")
else:
    client.transfer(recipient="0xabc...", amount=amount_to_send)

client.transfer(recipient, amount, idempotency_key=None, wait=True) -> dict

Send a payment from your agent account to a recipient address. The gateway automatically handles infrastructure abstraction, execution, and secure routing.

ParameterTypeDescription
recipientstrEVM-compatible blockchain address of the recipient.
amountfloatAmount of value to send (e.g. 5.0 = 5.00 credits).
idempotency_keystr | NonePrevents duplicate payments. Auto-generated if omitted. Pass a deterministic hash for loop safety.
waitboolIf True, blocks and polls until on-chain confirmation. If False, returns immediately with PENDING status.
python
receipt = client.transfer(
    recipient="0x742d35Cc6634C0532925a3b844...",
    amount=10.0,
    wait=True
)

print(receipt["txHash"])  # "0x..."
print(receipt["status"])  # "COMPLETE"

Understanding wait=True (Blockchain Finality Polling)

When wait=True (the default), the SDK submits the transaction to the Gateway and then polls the transaction status endpoint repeatedly until the blockchain confirms the transaction. This means your code blocks until on-chain finality is achieved — the receipt you get back is guaranteed to be settled. If it does not settle within 30 seconds, a TimeoutError is raised.

The polling interval uses exponential backoff (starting at 1s) and times out after the configured timeout value. For most chains, confirmation takes 2-10 seconds.

When to use wait=False

Set wait=False for high-throughput agents that need to fire-and-forget. The function returns immediately with a PENDING status and a transaction ID. You can poll the status later via GET /api/v1/agent/transaction/:id. This is useful for batch processing or when your agent has other work to do while the transaction settles.


client.get_history(limit=5) -> TransactionHistoryResponse

Fetch the transaction history for your authenticated agent. This allows your agent to recall previous payments and maintain contextual memory of its spending.

python
history = client.get_history(limit=5)

for tx in history.transactions:
    print(f"[{tx.createdAt}] {tx.type} {tx.amount} -> {tx.providerAddress} ({tx.state})")
    
if history.hasMore:
    print("More transactions available.")

client.smart_fetch(url, params=None, headers=None) -> Response

Fetch any URL and automatically negotiate payment if the server returns HTTP 402. Under the hood, smart_fetch wraps Python's requests.get() — it sends a standard GET request first, and only engages the payment flow if the server responds with a 402 paywall.

How it works internally

  1. Sends a standard GET request to the URL (using requests.get).
  2. If the response is 200 OK, returns the response directly — no payment involved.
  3. If the response is 402 Payment Required, parses the WWW-Authenticate header for the price and destination.
  4. Calls transfer() to pay the requested amount to the provider address.
  5. Retries the original GET request with a payment proof header attached.
  6. Returns the final Response object with the premium data.
python
# Works exactly like requests.get() for free APIs
response = client.smart_fetch("https://api.free-data.com/prices")

# But also handles paywalled APIs automatically
response = client.smart_fetch("https://api.premium-data.com/report")

# You can pass query params and custom headers
response = client.smart_fetch(
    "https://api.premium-data.com/search",
    params={"q": "NVIDIA earnings"},
    headers={"Accept": "application/json"}
)

if response.ok:
    print(response.json())

Spending Policies apply here too

Every payment triggered by smart_fetch goes through the same Spending Policy enforcement, idempotency checks, and optional allowlist validation as direct transfer() calls. See Security & Best Practices for details.


Vaults (High-Frequency Payments)

The Python SDK supports High-Frequency Payments (HFP) through Modexia Vaults. Vaults use cryptographic payment channels to allow agents to process thousands of transactions per second off-chain with zero latency and zero network fees per micro-transaction.

1. Open a Channel (Deposit)

python
# Open a channel with a max capacity of 1.00 credit
# Valid for 24 hours
channel = client.open_channel(
    provider="0x1c56...", 
    deposit=1.00, 
    duration_hours=24.0
)
print(f"Channel generated: {channel['channelId']}")

2. Fire High-Frequency Consume Calls

python
# 1,000 sub-second micro-transactions (0 network fees)
for i in range(1000):
    receipt = client.consume_channel(
        channel_id=channel['channelId'],
        amount=0.001
    )
    # The SDK generates an HMAC receipt instantly entirely locally/server-side

3. Close and Settle

python
# Finalize the channel on the ledger and refund unused balance
settle_receipt = client.settle_channel(channel_id=channel['channelId'])
print(f"Settled on-chain finality: {settle_receipt['settlementTxId']}")