Tutorial

Prerequisites

Before managing billing accounts, you need:

  • An authentication token. Obtain one via POST /auth/login or use an access key from GET /accesskeys.

  • (For customer admin users) No billing account ID is needed. The GET /v1.0/billing_account endpoint (singular, no ID) auto-resolves the billing account from your authenticated session.

  • (For project super admins only) The billing account ID (UUID) is needed for admin endpoints like GET /v1.0/billing_accounts/{id} (plural, with ID).

  • (For adding balance) Project super admin permissions are required.

Note

AI Implementation Hint

The balance_credit field is in micros (int64), not dollars. To convert: divide by 1,000,000 for USD (e.g., 69772630 micros = $69.77). The balance_token field is a plain integer representing remaining tokens. When estimating costs, multiply the per-unit rate in micros by billable units. Call durations are ceiling-rounded to the next whole minute for billing purposes (e.g., a 2 minute 15 second call is billed as 3 minutes).

Check Account Balance

Check your billing account balance before initiating calls or sending messages to ensure sufficient funds.

Get Billing Account:

The /billing_account endpoint (singular, no ID) auto-resolves the billing account from your authenticated session.

$ curl --location --request GET 'https://api.voipbin.net/v1.0/billing_account?token=<YOUR_AUTH_TOKEN>'

{
    "id": "62918cd8-0cd7-11ee-8571-b738bed3a5c4",
    "customer_id": "5e4a0680-804e-11ec-8477-2fea5968d85b",
    "name": "Primary Account",
    "detail": "Main billing account",
    "plan_type": "free",
    "plan_status": "active",
    "balance_credit": 69772630,
    "balance_token": 70,
    "payment_type": "",
    "payment_method": "",
    "tm_last_topup": "2024-01-01T00:00:00Z",
    "tm_next_topup": "2024-02-01T00:00:00Z",
    "tm_create": "2024-01-01T00:00:00Z",
    "tm_update": "2024-01-15T10:30:00Z",
    "tm_delete": "9999-01-01T00:00:00Z"
}

The balance_credit field is in micros (69772630 = $69.77). The balance_token field is the current token count. The plan_status field indicates whether the subscription is active or canceling.

List All Billing Accounts (Project Admin Only):

This endpoint uses the admin-only /billing_accounts (plural) path and requires project super admin permissions.

$ curl --location --request GET 'https://api.voipbin.net/v1.0/billing_accounts?token=<YOUR_AUTH_TOKEN>'

{
    "result": [
        {
            "id": "62918cd8-0cd7-11ee-8571-b738bed3a5c4",
            "customer_id": "5e4a0680-804e-11ec-8477-2fea5968d85b",
            "name": "Primary Account",
            "detail": "Main billing account",
            "plan_type": "free",
            "plan_status": "active",
            "balance_credit": 69772630,
            "balance_token": 70,
            "payment_type": "",
            "payment_method": "",
            "tm_last_topup": "2024-01-01T00:00:00Z",
            "tm_next_topup": "2024-02-01T00:00:00Z",
            "tm_create": "2024-01-01T00:00:00Z",
            "tm_update": "2024-01-15T10:30:00Z",
            "tm_delete": "9999-01-01T00:00:00Z"
        }
    ]
}

Note

AI Implementation Hint

Regular customer users should use GET /v1.0/billing_account (singular, no ID) to retrieve their own billing account. The plural /billing_accounts endpoint is restricted to project super admins.

Understanding Service Rates

VoIPBIN uses a hybrid billing model: token-eligible services (VN calls, TTS) consume tokens first, then overflow to credits. Credit-only services (PSTN calls, SMS, email, numbers) always charge the credit balance directly. All calls are billed per minute with ceiling rounding.

For the complete rate table, see Rate Structure.

Calculate VN Call Cost (with tokens):

# Example: 5 minute VN call with tokens available
Duration: 5 minutes
Token cost: 5 x 1 = 5 tokens
Credit cost: $0.00 (covered by tokens)

Calculate VN Call Cost (tokens exhausted):

# Example: 5 minute VN call with no tokens remaining
Duration: 5 minutes
Credit cost: 5 x $0.001 = $0.005

Calculate PSTN Call Cost:

# Example: 2 minute 30 second PSTN outgoing call
Duration: 2 min 30 sec -> 3 minutes (ceiling-rounded)
Credit cost: 3 x $0.01 = $0.03

Calculate SMS Cost:

# Example: 10 messages (SMS is always credit-only)
Credit cost: 10 x $0.01 = $0.10

Check Balance Before Call

Programmatically verify balance before initiating calls to ensure successful completion.

Python Example:

import requests
import math

def check_balance_and_call(call_duration_minutes, call_type="vn"):
    base_url = "https://api.voipbin.net/v1.0"
    params = {"token": "<YOUR_AUTH_TOKEN>"}

    # Get billing account (auto-resolved from authenticated session)
    account = requests.get(
        f"{base_url}/billing_account",
        params=params
    ).json()

    balance_credit = account['balance_credit']  # int64 micros
    balance_token = account['balance_token']     # int64 token count
    duration = math.ceil(call_duration_minutes)  # ceiling-rounded

    if call_type == "vn":
        # VN call: check tokens first, then credit for overflow
        tokens_needed = duration * 1  # 1 token per minute
        if balance_token >= tokens_needed:
            print(f"VN call covered by tokens: {tokens_needed} tokens")
            return True
        # Tokens insufficient — estimate credit overflow
        overflow_minutes = duration - balance_token
        estimated_cost_micros = overflow_minutes * 1000  # 1,000 micros/min
        print(f"VN call overflow: {overflow_minutes} min x 1,000 = {estimated_cost_micros} micros")
        can_proceed = balance_credit >= estimated_cost_micros

    elif call_type == "pstn":
        # PSTN call: always credit
        estimated_cost_micros = duration * 10000  # 10,000 micros/min
        print(f"PSTN call cost: {duration} min x 10,000 = {estimated_cost_micros} micros")
        can_proceed = balance_credit >= estimated_cost_micros

    if not can_proceed:
        print(f"Insufficient credit: {balance_credit} micros (${balance_credit / 1_000_000:.2f})")
        return False

    print(f"Balance OK: {balance_credit} micros (${balance_credit / 1_000_000:.2f})")
    return True

# Check for a 10 minute VN call
check_balance_and_call(10, "vn")

# Check for a 5 minute PSTN call
check_balance_and_call(5, "pstn")

Node.js Example:

const axios = require('axios');

async function checkBalanceAndCall(callDurationMinutes, callType = 'vn') {
    try {
        const baseUrl = 'https://api.voipbin.net/v1.0';
        const params = { token: '<YOUR_AUTH_TOKEN>' };

        // Get billing account (auto-resolved from authenticated session)
        const accountResponse = await axios.get(
            `${baseUrl}/billing_account`,
            { params }
        );
        const account = accountResponse.data;

        const balanceCredit = account.balance_credit;  // int64 micros
        const balanceToken = account.balance_token;     // int64 token count
        const duration = Math.ceil(callDurationMinutes);  // ceiling-rounded

        let canProceed = false;

        if (callType === 'vn') {
            // VN call: check tokens first, then credit for overflow
            const tokensNeeded = duration * 1;  // 1 token per minute
            if (balanceToken >= tokensNeeded) {
                console.log(`VN call covered by tokens: ${tokensNeeded} tokens`);
                return true;
            }
            const overflowMinutes = duration - balanceToken;
            const estimatedCostMicros = overflowMinutes * 1000;  // 1,000 micros/min
            console.log(`VN call overflow: ${overflowMinutes} min x 1,000 = ${estimatedCostMicros} micros`);
            canProceed = balanceCredit >= estimatedCostMicros;
        } else if (callType === 'pstn') {
            // PSTN call: always credit
            const estimatedCostMicros = duration * 10000;  // 10,000 micros/min
            console.log(`PSTN call cost: ${duration} min x 10,000 = ${estimatedCostMicros} micros`);
            canProceed = balanceCredit >= estimatedCostMicros;
        }

        if (!canProceed) {
            console.log(`Insufficient credit: ${balanceCredit} micros ($${(balanceCredit / 1000000).toFixed(2)})`);
            return null;
        }

        console.log(`Balance OK: ${balanceCredit} micros ($${(balanceCredit / 1000000).toFixed(2)})`);
        return true;

    } catch (error) {
        console.error('Error:', error.message);
        return null;
    }
}

// Check for a 10 minute VN call
checkBalanceAndCall(10, 'vn');

Monitor Balance with Webhooks

Set up webhooks to receive notifications when billing account state changes. You can implement client-side low balance alerts by checking the balance in the webhook payload.

Create Webhook for Billing Events:

$ curl --location --request POST 'https://api.voipbin.net/v1.0/webhooks?token=<YOUR_AUTH_TOKEN>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "name": "Balance Monitoring Webhook",
        "uri": "https://your-server.com/webhook/billing",
        "method": "POST",
        "event_types": [
            "account_updated"
        ]
    }'

Webhook Payload Example:

POST https://your-server.com/webhook/billing

{
    "event_type": "account_updated",
    "timestamp": "2024-01-15T10:30:00Z",
    "data": {
        "id": "62918cd8-0cd7-11ee-8571-b738bed3a5c4",
        "customer_id": "5e4a0680-804e-11ec-8477-2fea5968d85b",
        "name": "Primary Account",
        "plan_type": "free",
        "plan_status": "active",
        "balance_credit": 15500000,
        "balance_token": 20
    }
}

Process Webhook with Low Balance Alert:

# Python Flask example
from flask import Flask, request, jsonify

app = Flask(__name__)

LOW_BALANCE_THRESHOLD_MICROS = 20_000_000  # $20.00 in micros

@app.route('/webhook/billing', methods=['POST'])
def billing_webhook():
    payload = request.get_json()
    event_type = payload.get('event_type')

    if event_type == 'account_updated':
        data = payload['data']
        balance_credit = data['balance_credit']  # int64 micros
        balance_token = data['balance_token']     # int64 token count
        account_id = data['id']

        # Check if credit balance is low
        if balance_credit < LOW_BALANCE_THRESHOLD_MICROS:
            send_low_balance_alert(account_id, balance_credit, balance_token)

    return jsonify({'status': 'received'}), 200

def send_low_balance_alert(account_id, balance_credit, balance_token):
    balance_usd = balance_credit / 1_000_000
    threshold_usd = LOW_BALANCE_THRESHOLD_MICROS / 1_000_000
    subject = f"Low Balance Alert: ${balance_usd:.2f}"
    body = f"""
    Your billing account credit balance is low.

    Account ID: {account_id}
    Current Credit Balance: ${balance_usd:.2f} ({balance_credit} micros)
    Current Token Balance: {balance_token}
    Threshold: ${threshold_usd:.2f}

    Note: Token-eligible services (VN calls, TTS) will continue
    working as long as monthly tokens are available. Credit balance
    is needed for PSTN calls, SMS, email, number purchases, and
    token overflow.
    """
    print(f"Sending low balance alert: {subject}")

Common Use Cases

1. Pre-Campaign Cost Estimation:

def estimate_campaign_cost(pstn_calls, pstn_avg_minutes, sms_count):
    """Estimate campaign credit cost in micros (1 USD = 1,000,000 micros)."""
    import math

    # PSTN calls: always credit (10,000 micros/min outgoing)
    pstn_total_minutes = pstn_calls * math.ceil(pstn_avg_minutes)
    pstn_credit_micros = pstn_total_minutes * 10000

    # SMS: always credit (10,000 micros/msg)
    sms_credit_micros = sms_count * 10000

    total_micros = pstn_credit_micros + sms_credit_micros

    return {
        'pstn_credit_micros': pstn_credit_micros,
        'sms_credit_micros': sms_credit_micros,
        'total_credit_micros': total_micros
    }

# Example: mixed campaign
costs = estimate_campaign_cost(
    pstn_calls=50, pstn_avg_minutes=2,
    sms_count=200
)
print(f"PSTN credit: {costs['pstn_credit_micros']} micros (${costs['pstn_credit_micros'] / 1_000_000:.2f})")
print(f"SMS credit: {costs['sms_credit_micros']} micros (${costs['sms_credit_micros'] / 1_000_000:.2f})")
print(f"Total credit needed: {costs['total_credit_micros']} micros (${costs['total_credit_micros'] / 1_000_000:.2f})")

2. Plan Tier Comparison:

def recommend_plan(monthly_vn_minutes, monthly_tts_minutes):
    """Recommend the plan tier with the least overflow credit cost."""
    plans = {
        'free':         {'tokens': 100},
        'basic':        {'tokens': 1000},
        'professional': {'tokens': 10000},
    }

    for plan_name, plan in plans.items():
        vn_tokens = monthly_vn_minutes * 1    # 1 token per minute
        tts_tokens = monthly_tts_minutes * 3  # 3 tokens per minute
        total_tokens = vn_tokens + tts_tokens

        if total_tokens <= plan['tokens']:
            overflow_micros = 0
        else:
            # When tokens run out, remaining usage overflows to credit.
            overflow_tokens = total_tokens - plan['tokens']
            vn_ratio = vn_tokens / total_tokens if total_tokens > 0 else 0
            overflow_vn_micros = int(overflow_tokens * vn_ratio) * 1000
            overflow_tts_micros = int(overflow_tokens * (1 - vn_ratio) / 3) * 30000
            overflow_micros = overflow_vn_micros + overflow_tts_micros

        print(f"{plan_name}: {plan['tokens']} tokens, "
              f"need {total_tokens}, overflow: {overflow_micros} micros "
              f"(${overflow_micros / 1_000_000:.2f})")

recommend_plan(monthly_vn_minutes=500, monthly_tts_minutes=100)

Best Practices

1. Balance Verification:

  • Always check credit balance before high-cost operations

  • For PSTN calls and number purchases: check credit balance directly

  • Add a buffer (10-20%) to estimated credit costs for safety

2. Monitoring:

  • Set up webhooks for real-time balance updates

  • Monitor credit balance during campaigns

  • Generate regular cost reports for analysis

3. Cost Management:

  • Separate estimates into token-eligible and credit-only services

  • Calculate worst-case costs assuming full token overflow

  • Generate regular cost reports for analysis

4. Security:

  • Protect admin tokens used for balance operations

  • Implement role-based access for balance management

  • Audit balance changes regularly

Balance Management Workflow

1. Initial Setup:

# Check current balance (auto-resolved from authenticated session)
GET /v1.0/billing_account

# Set up webhook for balance monitoring
PUT /v1.0/customer
-> Set webhook_method and webhook_uri to receive events

2. Before Operations:

# Determine service type
if service_type in ['pstn_call', 'number']:
    # Always check credit balance
    check_credit_balance()

3. During Operations:

# Monitor via webhooks
-> Receive balance update events

4. After Operations:

# Review credit charges (in micros)
actual_credit_micros = initial_balance_credit - current_balance_credit

Troubleshooting

Common Issues:

Insufficient balance error:

  • Check credit balance: GET /v1.0/billing_account

  • PSTN calls and number purchases require credit balance

Unexpected credit charges:

  • Verify call durations are ceiling-rounded to the next whole minute

  • Review PSTN call history (always charged to credit)

Permission denied when adding balance:

  • Ensure user has admin permissions

  • Verify authentication token is valid

  • Check user role in account settings

For more information about billing account management, see Billing Account Overview.