BillingPayment Credits

Chapter 5: Payment & Credits

Overview

The Polysystems Backend API uses a prepaid credit system powered by x402 cryptocurrency payments. This chapter explains how to add credits to your account, manage transactions, and understand the payment flow.

Credit System Architecture

User Account
    ├── Credit Balance (USD)
    ├── Payment Methods (BTC, ETH, SOL)
    ├── Transaction History
    └── Spending Limits (per Access Token)

API Request → Pricing Check → Balance Check → Deduct Credits → Execute Request

How Credits Work

Credit Model

  • Currency: All credits are denominated in USD
  • Precision: Prices calculated to 4 decimal places ($0.0001)
  • Minimum Balance: $0.00 (but requests require sufficient balance)
  • No Expiration: Credits never expire
  • Non-Refundable: Credits cannot be withdrawn or refunded

Credit Flow

1. Add Credits via Crypto Payment

2. Credits Added to Account Balance

3. Make API Requests

4. Credits Automatically Deducted

5. Transaction Recorded

6. Balance Updated

Checking Your Balance

Get Current Balance

curl -X GET https://api.polysystems.ai/api/payments/credits/balance \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response:

{
  "user_id": "user-123e4567-e89b-12d3-a456-426614174000",
  "balance": 47.3250,
  "currency": "USD",
  "last_updated": "2024-01-15T14:30:00Z"
}

Balance Information

  • balance: Current available credits in USD
  • currency: Always USD
  • last_updated: Timestamp of last balance change

x402 Payment System

What is x402?

x402 is a payment protocol that enables direct cryptocurrency payments for API usage. It provides:

  • Direct Crypto Payments: No intermediaries or payment processors
  • Multiple Currencies: BTC, ETH, and SOL supported
  • Automatic Confirmation: Blockchain monitoring for payment verification
  • Instant Credit: Credits added immediately after confirmation

Supported Cryptocurrencies

CurrencySymbolRequired ConfirmationsAvg Confirmation Time
BitcoinBTC3~30 minutes
EthereumETH12~3 minutes
SolanaSOL1~30 seconds

Creating a Payment

Step 1: Get Payment Methods

Check available payment methods:

curl -X GET https://api.polysystems.ai/api/payments/payments/methods \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response:

{
  "methods": [
    {
      "currency": "BTC",
      "name": "Bitcoin",
      "required_confirmations": 3,
      "average_confirmation_time": "30 minutes",
      "network_fee_estimate": "low"
    },
    {
      "currency": "ETH",
      "name": "Ethereum",
      "required_confirmations": 12,
      "average_confirmation_time": "3 minutes",
      "network_fee_estimate": "medium"
    },
    {
      "currency": "SOL",
      "name": "Solana",
      "required_confirmations": 1,
      "average_confirmation_time": "30 seconds",
      "network_fee_estimate": "low"
    }
  ]
}

Step 2: Create Payment Request

curl -X POST https://api.polysystems.ai/api/payments/payments \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_usd": 50.00,
    "currency": "ETH"
  }'

Request Parameters:

  • amount_usd (required): Amount in USD to add to balance
  • currency (required): Cryptocurrency to use (BTC, ETH, or SOL)
  • expires_in_minutes (optional): Payment expiration (default: 1440 = 24 hours)

Response:

{
  "id": "pay-123e4567-e89b-12d3-a456-426614174000",
  "payment_hash": "x402_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "currency": "ETH",
  "amount_crypto": 0.0275,
  "amount_usd": 50.00,
  "to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "status": "pending",
  "confirmations": 0,
  "required_confirmations": 12,
  "tx_hash": null,
  "created_at": "2024-01-15T15:00:00Z",
  "expires_at": "2024-01-16T15:00:00Z"
}

Step 3: Send Cryptocurrency

Send the exact amount_crypto to the to_address:

Important:

  • ⚠️ Send exactly the amount specified in amount_crypto
  • ⚠️ Send to the exact address in to_address
  • ⚠️ Complete transaction before expires_at
  • ⚠️ Include sufficient network fees for timely confirmation

Step 4: Wait for Confirmation

The system automatically monitors the blockchain for your transaction. You can check status:

curl -X GET https://api.polysystems.ai/api/payments/payments/{payment_id} \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response (Confirming):

{
  "id": "pay-123e4567-e89b-12d3-a456-426614174000",
  "payment_hash": "x402_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "currency": "ETH",
  "amount_crypto": 0.0275,
  "amount_usd": 50.00,
  "to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "status": "confirming",
  "confirmations": 6,
  "required_confirmations": 12,
  "tx_hash": "0x1234567890abcdef...",
  "created_at": "2024-01-15T15:00:00Z",
  "confirmed_at": null,
  "expires_at": "2024-01-16T15:00:00Z"
}

Response (Confirmed):

{
  "id": "pay-123e4567-e89b-12d3-a456-426614174000",
  "payment_hash": "x402_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "currency": "ETH",
  "amount_crypto": 0.0275,
  "amount_usd": 50.00,
  "to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "status": "confirmed",
  "confirmations": 12,
  "required_confirmations": 12,
  "tx_hash": "0x1234567890abcdef...",
  "created_at": "2024-01-15T15:00:00Z",
  "confirmed_at": "2024-01-15T15:15:00Z",
  "expires_at": "2024-01-16T15:00:00Z"
}

Payment Status States

StatusDescriptionNext Action
pendingWaiting for transactionSend cryptocurrency
confirmingTransaction detected, waiting for confirmationsWait
confirmedPayment confirmed, credits addedUse API
failedTransaction failedCreate new payment
expiredPayment window expiredCreate new payment

Listing Payments

View all your payment history:

curl -X GET "https://api.polysystems.ai/api/payments/payments?limit=10&offset=0" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response:

{
  "payments": [
    {
      "id": "pay-123",
      "amount_usd": 50.00,
      "currency": "ETH",
      "status": "confirmed",
      "created_at": "2024-01-15T15:00:00Z",
      "confirmed_at": "2024-01-15T15:15:00Z"
    },
    {
      "id": "pay-456",
      "amount_usd": 100.00,
      "currency": "BTC",
      "status": "confirmed",
      "created_at": "2024-01-10T10:00:00Z",
      "confirmed_at": "2024-01-10T10:45:00Z"
    }
  ],
  "total": 2,
  "limit": 10,
  "offset": 0
}

Transaction History

Every credit deduction creates a transaction record.

List Transactions

curl -X GET "https://api.polysystems.ai/api/payments/transactions?limit=20&offset=0" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response:

{
  "transactions": [
    {
      "id": "tx-123e4567-e89b-12d3-a456-426614174000",
      "user_id": "user-123",
      "amount": 0.0020,
      "type": "debit",
      "status": "completed",
      "description": "API request: POST /api/hub/agents/chat",
      "reference_id": "key-789",
      "metadata": {
        "route": "/api/hub/agents/chat",
        "method": "POST",
        "price": 0.0020
      },
      "created_at": "2024-01-15T14:30:00Z"
    },
    {
      "id": "tx-456e7890-e12b-34d5-a678-901234567890",
      "user_id": "user-123",
      "amount": 50.00,
      "type": "credit",
      "status": "completed",
      "description": "x402 payment confirmed",
      "reference_id": "pay-123",
      "metadata": {
        "payment_hash": "x402_...",
        "currency": "ETH"
      },
      "created_at": "2024-01-15T15:15:00Z"
    }
  ],
  "total": 2,
  "limit": 20,
  "offset": 0
}

Transaction Types

TypeDescriptionAmount
creditCredits added to accountPositive
debitCredits deducted for API usageNegative (shown as positive)
refundCredits refunded (rare)Positive
adjustmentManual adjustment by adminPositive or Negative

Transaction Status

StatusDescription
pendingTransaction initiated
completedTransaction finalized
failedTransaction failed
reversedTransaction reversed

Get Transaction Details

curl -X GET https://api.polysystems.ai/api/payments/transactions/{transaction_id} \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response:

{
  "id": "tx-123e4567-e89b-12d3-a456-426614174000",
  "user_id": "user-123e4567-e89b-12d3-a456-426614174000",
  "amount": 0.0020,
  "type": "debit",
  "status": "completed",
  "description": "API request: POST /api/hub/agents/chat",
  "reference_id": "key-789abc",
  "metadata": {
    "route": "/api/hub/agents/chat",
    "method": "POST",
    "price": 0.0020,
    "tokens_used": 150,
    "model": "gpt-4"
  },
  "created_at": "2024-01-15T14:30:00Z",
  "updated_at": "2024-01-15T14:30:01Z"
}

Transaction Statistics

Get aggregated statistics about your transactions:

curl -X GET "https://api.polysystems.ai/api/payments/transactions/stats?start_date=2024-01-01&end_date=2024-01-31" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response:

{
  "period": {
    "start_date": "2024-01-01T00:00:00Z",
    "end_date": "2024-01-31T23:59:59Z"
  },
  "summary": {
    "total_credits_added": 150.00,
    "total_credits_spent": 47.65,
    "net_change": 102.35,
    "transaction_count": 2345,
    "average_transaction_amount": 0.0203
  },
  "by_type": {
    "credit": {
      "count": 3,
      "total_amount": 150.00
    },
    "debit": {
      "count": 2342,
      "total_amount": 47.65
    }
  },
  "by_day": [
    {
      "date": "2024-01-15",
      "credits_spent": 5.23,
      "transaction_count": 156
    }
  ],
  "top_routes": [
    {
      "route": "/api/hub/agents/chat",
      "count": 1234,
      "total_cost": 24.68
    },
    {
      "route": "/api/hub/memory",
      "count": 567,
      "total_cost": 11.34
    }
  ]
}

Automatic Payment Processing

Background Jobs

The system runs automated jobs to:

  1. Monitor Blockchain: Check for incoming transactions every 30 seconds
  2. Update Confirmations: Track confirmation counts for pending payments
  3. Mark Expired: Automatically expire payments past their deadline
  4. Send Webhooks: Notify on payment status changes
  5. Add Credits: Automatically credit accounts when payments confirm

Webhook Notifications

Configure webhooks to receive payment notifications (see Chapter 8):

Payment Events:

  • payment.created - New payment initiated
  • payment.confirming - Transaction detected on blockchain
  • payment.confirmed - Payment confirmed, credits added
  • payment.failed - Payment failed
  • payment.expired - Payment window expired

Example Webhook Payload:

{
  "event_id": "evt-123",
  "event_type": "payment.confirmed",
  "timestamp": "2024-01-15T15:15:00Z",
  "data": {
    "payment_id": "pay-123",
    "amount_usd": 50.00,
    "currency": "ETH",
    "user_id": "user-123",
    "new_balance": 97.32
  },
  "signature": "sha256_signature_here"
}

Payment Best Practices

1. Choose Appropriate Cryptocurrency

Bitcoin (BTC)

  • ✅ Most secure (highest confirmations)
  • ✅ Widely available
  • ❌ Slower confirmation (30+ minutes)
  • ❌ Higher network fees during congestion

Ethereum (ETH)

  • ✅ Good balance of speed and security
  • ✅ Moderate confirmation time (3 minutes)
  • ❌ Network fees can be high during congestion

Solana (SOL)

  • ✅ Fastest confirmation (30 seconds)
  • ✅ Low network fees
  • ❌ Fewer confirmations (less secure for large amounts)

Recommendation:

  • Small amounts (11-50): Use SOL for speed
  • Medium amounts (5050-500): Use ETH for balance
  • Large amounts ($500+): Use BTC for security

2. Payment Amount Strategy

# Good: Add credits in bulk to reduce transaction fees
curl -X POST https://api.polysystems.ai/api/payments/payments \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -d '{"amount_usd": 100.00, "currency": "ETH"}'
 
# Avoid: Many small payments (higher cumulative fees)
# Multiple $10 payments instead of one $100 payment

3. Monitor Payment Status

#!/bin/bash
# payment_monitor.sh
 
PAYMENT_ID=$1
JWT_TOKEN=$PS_JWT_TOKEN
 
while true; do
  STATUS=$(curl -s -X GET \
    "https://api.polysystems.ai/api/payments/payments/$PAYMENT_ID" \
    -H "Authorization: Bearer $JWT_TOKEN" \
    | jq -r '.status')
  
  echo "Payment status: $STATUS"
  
  if [ "$STATUS" = "confirmed" ]; then
    echo "Payment confirmed! Credits added."
    break
  elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ]; then
    echo "Payment $STATUS. Please create a new payment."
    break
  fi
  
  sleep 30
done

4. Set Balance Alerts

Monitor your balance and set up alerts:

import os
import requests
 
def check_balance_alert(threshold=10.0):
    """Alert if balance falls below threshold"""
    response = requests.get(
        'https://api.polysystems.ai/api/payments/credits/balance',
        headers={'Authorization': f'Bearer {os.getenv("PS_JWT_TOKEN")}'}
    )
    
    balance = response.json()['balance']
    
    if balance < threshold:
        # Send alert (email, SMS, Slack, etc.)
        print(f"⚠️  LOW BALANCE ALERT: ${balance}")
        print(f"Please add credits to avoid service interruption.")
        return True
    
    return False
 
# Run periodically
if __name__ == '__main__':
    check_balance_alert(threshold=10.0)

5. Pre-fund for Production

For production applications:

# Calculate estimated monthly usage
monthly_requests = 100000  # 100k requests/month
avg_cost_per_request = 0.0020  # $0.002 per request
monthly_cost = monthly_requests * avg_cost_per_request  # $200
 
# Add 20% buffer
recommended_balance = monthly_cost * 1.2  # $240
 
print(f"Recommended initial balance: ${recommended_balance}")

Troubleshooting

Payment Not Appearing

Problem: Sent cryptocurrency but payment status still “pending”

Solutions:

  1. Verify you sent the exact amount to the exact address
  2. Check blockchain explorer for transaction confirmation
  3. Wait for required confirmations (varies by currency)
  4. Ensure transaction has sufficient network fee
  5. Check payment hasn’t expired

Payment Expired

Problem: Payment shows “expired” status

Solution:

# Create a new payment
curl -X POST https://api.polysystems.ai/api/payments/payments \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -d '{"amount_usd": 50.00, "currency": "ETH"}'
 
# Send crypto to new address before expiration

Wrong Amount Sent

Problem: Sent incorrect cryptocurrency amount

Solutions:

  • If you sent more: Credits will be added based on actual amount received
  • If you sent less: Payment may fail or be credited with received amount
  • Contact support for manual resolution if needed

Confirmation Taking Too Long

Problem: Payment stuck in “confirming” for extended period

Possible Causes:

  • Network congestion (especially Bitcoin/Ethereum)
  • Low transaction fee (transaction delayed)
  • Blockchain issues

Solutions:

  1. Check blockchain explorer for confirmation status
  2. For Bitcoin: Consider using Replace-By-Fee (RBF) to increase fee
  3. For Ethereum: Consider increasing gas price
  4. Wait for next block (may take longer during congestion)
  5. Contact support if stuck for more than 2x expected time

Advanced Payment Features

Programmatic Payment Workflow

import os
import time
import requests
 
class PaymentManager:
    def __init__(self, jwt_token):
        self.jwt_token = jwt_token
        self.base_url = "https://api.polysystems.ai"
        self.headers = {
            "Authorization": f"Bearer {jwt_token}",
            "Content-Type": "application/json"
        }
    
    def create_payment(self, amount_usd, currency="ETH"):
        """Create a new payment"""
        response = requests.post(
            f"{self.base_url}/api/payments/payments",
            headers=self.headers,
            json={
                "amount_usd": amount_usd,
                "currency": currency
            }
        )
        return response.json()
    
    def check_payment_status(self, payment_id):
        """Check payment status"""
        response = requests.get(
            f"{self.base_url}/api/payments/payments/{payment_id}",
            headers=self.headers
        )
        return response.json()
    
    def wait_for_confirmation(self, payment_id, timeout=3600, check_interval=30):
        """Wait for payment confirmation with timeout"""
        start_time = time.time()
        
        while time.time() - start_time < timeout:
            payment = self.check_payment_status(payment_id)
            status = payment['status']
            
            print(f"Status: {status}, Confirmations: {payment['confirmations']}/{payment['required_confirmations']}")
            
            if status == 'confirmed':
                return True
            elif status in ['failed', 'expired']:
                return False
            
            time.sleep(check_interval)
        
        print("Timeout waiting for confirmation")
        return False
    
    def get_balance(self):
        """Get current balance"""
        response = requests.get(
            f"{self.base_url}/api/payments/credits/balance",
            headers=self.headers
        )
        return response.json()['balance']
 
# Usage
manager = PaymentManager(os.getenv('PS_JWT_TOKEN'))
 
# Check balance
balance = manager.get_balance()
print(f"Current balance: ${balance}")
 
# If low, create payment
if balance < 10.0:
    payment = manager.create_payment(50.0, "ETH")
    print(f"Payment created: {payment['id']}")
    print(f"Send {payment['amount_crypto']} ETH to {payment['to_address']}")
    
    # Wait for confirmation
    if manager.wait_for_confirmation(payment['id']):
        new_balance = manager.get_balance()
        print(f"Payment confirmed! New balance: ${new_balance}")

Summary

In this chapter, you learned:

  • ✅ How the prepaid credit system works
  • ✅ How to check your account balance
  • ✅ How to create and manage x402 payments
  • ✅ Supported cryptocurrencies and their characteristics
  • ✅ Payment status lifecycle and monitoring
  • ✅ Transaction history and statistics
  • ✅ Best practices for payment management
  • ✅ Troubleshooting common payment issues
  • ✅ Programmatic payment automation

Next Steps