Usage API

The Poe Usage API provides endpoints to monitor your current point balance and retrieve your usage history. These endpoints help you track your consumption and manage your API usage effectively.

Key features:

  • Check your current point balance
  • Retrieve detailed usage history with pagination
  • Monitor usage across all your API calls
  • Track cost per individual query

All Usage API endpoints require authentication using your Poe API key and return data in JSON format.

Authentication

All Usage API endpoints require authentication using your Poe API key in the Authorization header:

Authorization: Bearer YOUR_POE_API_KEY

You can get your API key from https://poe.com/api_key.

Endpoints

Get Current Balance

Retrieve your current point balance, including both plan points and add-on points.

GET https://api.poe.com/usage/current_balance

Headers:

  • Authorization: Bearer YOUR_POE_API_KEY (required)

Response:

{
  "current_point_balance": 1500
}

Response Fields:

  • current_point_balance (integer): Your current available points

Example:

curl -X GET "https://api.poe.com/usage/current_balance" \
  -H "Authorization: Bearer YOUR_POE_API_KEY"
import requests

headers = {
    "Authorization": "Bearer YOUR_POE_API_KEY"
}

response = requests.get(
    "https://api.poe.com/usage/current_balance",
    headers=headers
)

balance_data = response.json()
print(f"Current balance: {balance_data['current_point_balance']} points")
const fetch = require('node-fetch');

const response = await fetch('https://api.poe.com/usage/current_balance', {
  headers: {
    'Authorization': 'Bearer YOUR_POE_API_KEY'
  }
});

const balanceData = await response.json();
console.log(`Current balance: ${balanceData.current_point_balance} points`);

Get Usage History

Retrieve your usage history with detailed information about each API call. Entries are fetched by creation time, descending, so the most recent usage histories appear first. You can fetch data up to 30 days old.

GET https://api.poe.com/usage/points_history

Headers:

  • Authorization: Bearer YOUR_POE_API_KEY (required)

Query Parameters:

  • limit (integer, optional): Number of entries to return. Maximum 100, default 20.
  • starting_after (string, optional): Pagination cursor. Use the query_id from the last entry of a previous response to get the next page.

Response:

{
  "has_more": true,
  "length": 20,
  "data": [
    {
      "app_name": "Claude-3.5-Sonnet",
      "creation_time": 1704825600,
      "query_id": "2Nhd9xBFbLcXEwmNj",
      "cost_points": 25
    },
    {
      "app_name": "GPT-4",
      "creation_time": 1704825300,
      "query_id": "2Nhd9xBFbLcXEwmNk",
      "cost_points": 50
    }
  ]
}

Response Fields:

  • has_more (boolean): Whether there are more entries available for pagination
  • length (integer): Number of entries in the current response
  • data (array): Array of usage entries, each containing:
    • bot_name (string): Name of the bot or model used
    • creation_time (integer): Unix timestamp in microseconds when the query was created
    • query_id (string): Unique identifier for the query (used for pagination)
    • cost_points (integer): Number of points consumed by this query
    • usage_type (string): Descriptor for where the points were used
    • chat_name (string): Chat name, if points were used on a chat. Populated if usage_type==Chat
    • App name (string): Canvas app name, if points were used on a canvas app. Populated if usage_type==Canvas App

Examples:

# Get recent usage (default 20 entries)
curl -X GET "https://api.poe.com/usage/points_history" \
  -H "Authorization: Bearer YOUR_POE_API_KEY"

# Get specific number of entries
curl -X GET "https://api.poe.com/usage/points_history?limit=50" \
  -H "Authorization: Bearer YOUR_POE_API_KEY"

# Paginate results (get next page after specific query_id)
curl -X GET "https://api.poe.com/usage/points_history?starting_after=2Nhd9xBFbLcXEwmNj&limit=20" \
  -H "Authorization: Bearer YOUR_POE_API_KEY"
import requests
from datetime import datetime

headers = {
    "Authorization": "Bearer YOUR_POE_API_KEY"
}

# Get recent usage history
response = requests.get(
    "https://api.poe.com/usage/points_history",
    headers=headers,
    params={"limit": 50}
)

usage_data = response.json()

print(f"Retrieved {usage_data['length']} entries")
print(f"Has more data: {usage_data['has_more']}")

for entry in usage_data['data']:
    # Convert microseconds to seconds for datetime
    created_time = datetime.fromtimestamp(entry['creation_time'] / 1_000_000)
    print(f"{created_time}: {entry['app_name']} - {entry['cost_points']} points")

# Pagination example
if usage_data['has_more']:
    last_query_id = usage_data['data'][-1]['query_id']

    next_response = requests.get(
        "https://api.poe.com/usage/points_history",
        headers=headers,
        params={"starting_after": last_query_id, "limit": 50}
    )

    next_data = next_response.json()
    print(f"Next page: {next_data['length']} entries")
const fetch = require('node-fetch');

const headers = {
  'Authorization': 'Bearer YOUR_POE_API_KEY'
};

// Get usage history
const response = await fetch('https://api.poe.com/usage/points_history?limit=50', {
  headers
});

const usageData = await response.json();

console.log(`Retrieved ${usageData.length} entries`);
console.log(`Has more data: ${usageData.has_more}`);

usageData.data.forEach(entry => {
  // Convert microseconds to milliseconds for Date constructor
  const createdTime = new Date(entry.creation_time / 1000);
  console.log(`${createdTime.toISOString()}: ${entry.app_name} - ${entry.cost_points} points`);
});

// Pagination example
if (usageData.has_more) {
  const lastQueryId = usageData.data[usageData.data.length - 1].query_id;

  const nextResponse = await fetch(
    `https://api.poe.com/usage/points_history?starting_after=${lastQueryId}&limit=50`,
    { headers }
  );

  const nextData = await nextResponse.json();
  console.log(`Next page: ${nextData.length} entries`);
}

Error Responses

All Usage API endpoints return standard HTTP status codes and JSON error responses:

401 Unauthorized

Missing or invalid API Key:

{
  "error": {
    "message": "Incorrect API key provided. You can find your API key at https://poe.com/api_key.",
    "type": "authentication_error",
    "code": "invalid_api_key"
  }
}

Use Cases

Monitoring and Alerting

import requests

def check_balance_and_alert(api_key, threshold=100):
    """Check balance and alert if below threshold"""
    headers = {"Authorization": f"Bearer {api_key}"}

    response = requests.get(
        "https://api.poe.com/usage/current_balance",
        headers=headers
    )

    balance = response.json()['current_point_balance']

    if balance < threshold:
        print(f"⚠️ Low balance alert: {balance} points remaining")
        return False

    print(f"✅ Balance OK: {balance} points")
    return True

Usage Analytics

import requests
from collections import defaultdict
from datetime import datetime, timedelta
import time

def analyze_usage_by_model(api_key, days=7):
    """Analyze usage patterns by model over the specified number of days"""
    headers = {"Authorization": f"Bearer {api_key}"}

    # Calculate cutoff timestamp for filtering (in microseconds)
    cutoff_time = (time.time() - (days * 24 * 60 * 60)) * 1_000_000

    filtered_entries = []
    starting_after = None

    # Collect usage data within the time window
    while True:
        params = {"limit": 100}
        if starting_after:
            params["starting_after"] = starting_after

        response = requests.get(
            "https://api.poe.com/usage/points_history",
            headers=headers,
            params=params
        )

        data = response.json()

        # Filter entries by creation_time (microseconds)
        for entry in data['data']:
            if entry['creation_time'] >= cutoff_time:
                filtered_entries.append(entry)
            else:
                # Since entries are in descending order, we can stop when we hit older data
                break

        # Stop if we've hit data older than our cutoff or no more data
        if not data['has_more'] or (data['data'] and data['data'][-1]['creation_time'] < cutoff_time):
            break

        starting_after = data['data'][-1]['query_id']

    # Analyze by model
    model_usage = defaultdict(lambda: {"calls": 0, "total_cost": 0})

    for entry in filtered_entries:
        model = entry['app_name']
        model_usage[model]['calls'] += 1
        model_usage[model]['total_cost'] += entry['cost_points']

    # Print results
    print(f"Usage statistics for the last {days} days:\n")
    for model, stats in sorted(model_usage.items()):
        avg_cost = stats['total_cost'] / stats['calls'] if stats['calls'] > 0 else 0
        print(f"{model}: {stats['calls']} calls, {stats['total_cost']} total points, {avg_cost:.1f} avg per call")

    print(f"\nTotal entries analyzed: {len(filtered_entries)}")
    if filtered_entries:
        # Convert microseconds to seconds for datetime
        oldest = datetime.fromtimestamp(filtered_entries[-1]['creation_time'] / 1_000_000)
        newest = datetime.fromtimestamp(filtered_entries[0]['creation_time'] / 1_000_000)
        print(f"Date range: {oldest.strftime('%Y-%m-%d')} to {newest.strftime('%Y-%m-%d')}")