Skip to main content

Python client library for GAME trading API

Project description

GAME API Client

Simple Python client for the GAME trading API.

Python Compatibility

  • Python 3.8+ (compatible 3.8 - 3.14)
  • Tested on: 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14
  • Recommended: 3.11+ for best performance

Installation

Option 1: pip (recommended)

pip install game-api-client

Option 2: From source

git clone https://github.com/groupe-e/game-api-client.git
cd game-api-client
pip install -r requirements.txt
pip install -e .

Option 3: Poetry (for development)

git clone https://github.com/groupe-e/game-api-client.git
cd game-api-client
poetry install

Quick Start

# Copy environment template
cp .env.example .env

# Edit .env with your credentials
# GAME_API_TOKEN="your_personal_token"
# GAME_API_URL="https://your-game-api-url.com"
# GAME_API_VERIFY_SSL=false

# Run demo
python demo.py

Or programmatically:

import asyncio
from game_client import GameAPI

async def main():
    api = GameAPI(
        token="your_authentik_token",
        base_url="https://your-game-api-url.com"
    )
    
    # Test connection
    if await api.test_connection():
        print("Connected!")
    
    # Get data
    status = await api.get_status()
    trades = await api.get_trades()
    market = await api.get_market_data()

asyncio.run(main())

Environment Variables

Create a .env file:

GAME_API_TOKEN=your_authentik_personal_token
GAME_API_URL=https://your-game-api-url.com
GAME_API_VERIFY_SSL=false

Available Methods

Connection & Status

  • test_connection() - Test API connection and authentication
  • get_status() - Get API status and health information

Market Data

  • get_market_data(direction=None, duration=None, sort_by_price=False) - Get market data points
    • direction: "buy" or "sell" (optional)
    • duration: Time duration like "15m", "30m", "1h" (optional)
    • sort_by_price: Sort results so the best offer for each side comes first (sell ascending, buy descending)
  • get_market_best_offers(duration=None, top_n=None) - Get market offers grouped by contract/direction, best prices first
    • duration: Time duration filter like "15m", "30m", "1h" (optional)
    • top_n: Keep only the N best offers per direction per contract (optional)
  • get_trades(direction=None, duration=None) - Get trades with optional filters
    • direction: "buy" or "sell" (optional)
    • duration: Time duration like "15m", "1h" (optional)
  • get_market_ltp(market_zone=None) - Get last traded prices (LTP)
    • market_zone: Market zone like "10YCH-SWISSGRIDZ" (optional)
  • get_latest_ltp() - Get latest LTP per contract across all zones
    • Returns dict mapping contract_id -> {price, volume, timestamp, market_zones, latest_zone}

Order Management

  • get_orders(direction=None) - Get orders with optional filter
    • direction: "buy" or "sell" (optional)
  • find_order_by_id(order_id) - Find specific order by ID
    • order_id: Order ID (string or numeric)
  • create_order(order_data) - Create new order (single or bulk)
    • order_data: Order object or {"orders": [...]} for bulk
  • delete_order(order_id) - Delete order by ID
    • order_id: Order ID (handles both string and numeric formats)

Spot Data

  • get_spot_data() - Get spot market data
  • get_spot_status() - Get spot API status

Usage Examples

Basic Usage

import asyncio
from game_client import GameAPI

async def main():
    api = GameAPI(
        token="your_authentik_token",
        base_url="https://your-game-api-url.com"
    )
    
    # Test connection
    if await api.test_connection():
        print("✅ Connected to API!")
    
    # Get basic data
    status = await api.get_status()
    market_data = await api.get_market_data()
    
    print(f"API Status: {status['status']}")
    print(f"Market data points: {len(market_data)}")

asyncio.run(main())

Order Management

async def order_examples():
    api = GameAPI(token="your_token", base_url="https://api.example.com")
    
    # Get all orders
    orders = await api.get_orders()
    print(f"Found {len(orders)} orders")
    
    # Get only buy orders
    buy_orders = await api.get_orders(direction="buy")
    
    # Create a single displayed order
    from datetime import datetime, timedelta
    future_time = datetime.now() + timedelta(hours=4)
    
    single_order = {
        "side": "buy",
        "price": 100.0,
        "volume": 1.0,
        "date": future_time.strftime("%Y-%m-%d"),
        "start_time": "14:00",
        "end_time": "15:00", 
        "duration": "15m",
        "tz_offset_hours": 0,
        "state": "displayed"  # Visible on the market (default)
    }
    
    result = await api.create_order(single_order)
    print(f"Created order: {result['order_id']}")
    
    # Create a hidden order (not visible to other participants)
    hidden_order = {
        "side": "buy",
        "price": 100.0,
        "volume": 1.0,
        "date": future_time.strftime("%Y-%m-%d"),
        "start_time": "14:00",
        "end_time": "15:00", 
        "duration": "15m",
        "tz_offset_hours": 0,
        "state": "hidden"  # Hidden from other participants
    }
    
    result = await api.create_order(hidden_order)
    print(f"Created hidden order: {result['order_id']}")
    
    # Create bulk orders with mixed states
    bulk_orders = {
        "orders": [
            {
                "side": "buy",
                "price": 100.0,
                "volume": 1.0,
                "date": future_time.strftime("%Y-%m-%d"),
                "start_time": "14:00",
                "end_time": "15:00",
                "duration": "15m",
                "tz_offset_hours": 0,
                "state": "displayed"
            },
            {
                "side": "sell", 
                "price": 200.0,
                "volume": 0.5,
                "date": future_time.strftime("%Y-%m-%d"),
                "start_time": "14:00",
                "end_time": "15:00",
                "duration": "15m",
                "tz_offset_hours": 0,
                "state": "hidden"
            }
        ]
    }
    
    bulk_result = await api.create_order(bulk_orders)
    print(f"Created {len(bulk_result['created'])} orders")
    
    # Find specific order
    order = await api.find_order_by_id(result['order_id'])
    if order:
        print(f"Found order: {order['direction']} {order['volume']} @ {order['price']}")
    
    # Delete order
    delete_result = await api.delete_order(result['order_id'])
    print(f"Order deleted: {delete_result['status']}")

Market Data with Filters

async def market_data_examples():
    api = GameAPI(token="your_token", base_url="https://api.example.com")
    
    # Get all trades
    all_trades = await api.get_trades()
    
    # Get only buy trades
    buy_trades = await api.get_trades(direction="buy")
    
    # Get trades with specific duration
    short_trades = await api.get_trades(duration="15m")
    
    # Get market data, sorted so best offers come first
    sorted_market = await api.get_market_data(sort_by_price=True)
    print(f"Sorted market data: {len(sorted_market)} points")

    # Get best offers grouped by contract (useful for liquidity analysis)
    best_offers = await api.get_market_best_offers(duration="15m", top_n=5)
    for contract, sides in best_offers.items():
        print(f"Contract: {contract}")
        print(f"  Best buys:  {[o['price'] for o in sides.get('buy', [])]}")
        print(f"  Best sells: {[o['price'] for o in sides.get('sell', [])]}")

    # Get spot data
    spot_data = await api.get_spot_data()
    spot_status = await api.get_spot_status()

    # Get last traded prices (LTP)
    ltp_data = await api.get_market_ltp()
    print(f"LTP entries: {len(ltp_data)}")

    # Get LTP for specific zone
    ch_ltp = await api.get_market_ltp(market_zone="10YCH-SWISSGRIDZ")
    print(f"CH LTP entries: {len(ch_ltp)}")

    # Get latest LTP per contract (like market table view)
    latest_ltp = await api.get_latest_ltp()
    for contract, data in latest_ltp.items():
        print(f"{contract}: {data['price']} EUR ({data['latest_zone']})")

    print(f"Total trades: {len(all_trades)}")
    print(f"Buy trades: {len(buy_trades)}")
    print(f"Short duration trades: {len(short_trades)}")
    print(f"Spot data points: {len(spot_data)}")
    print(f"Spot status: {spot_status['status']}")

Error Handling

async def error_handling_example():
    api = GameAPI(token="your_token", base_url="https://api.example.com")
    
    try:
        # This might fail if order data is invalid
        result = await api.create_order({"invalid": "data"})
    except GameAPIError as e:
        print(f"API Error: {e}")
    
    try:
        # This might fail if order doesn't exist
        await api.delete_order("non_existent_id")
    except GameAPIError as e:
        print(f"Delete failed: {e}")
    
    # Safe order lookup
    order = await api.find_order_by_id("some_id")
    if order is None:
        print("Order not found")
    else:
        print(f"Found order: {order}")

Order Data Format

Required Fields

All orders must include these required fields:

{
    "side": "buy",           # REQUIRED: "buy" or "sell"
    "price": 100.0,          # REQUIRED: Any number (positive, negative, zero)
    "volume": 1.0,           # REQUIRED: Positive number (> 0)  
    "date": "2024-01-15",    # REQUIRED: Future date in YYYY-MM-DD format
    "start_time": "14:00",   # REQUIRED: HH:MM format (future time)
    "end_time": "15:00",     # REQUIRED: HH:MM format (after start_time)
    "duration": "15m",       # REQUIRED: Time duration ("15m", "30m", "1h", etc.)
    "tz_offset_hours": 0,    # OPTIONAL: Timezone offset from UTC (auto-detected if not provided)
    "options": {               # OPTIONAL: Additional order options
        "trader_suffixe": "my_bot"  # OPTIONAL: Suffix appended to trader name (max 50 chars)
    }
}

Field Constraints

side

  • Values: "buy" or "sell" (case-sensitive)
  • Required: Yes

price

  • Type: Number (float or int)
  • Required: Yes
  • Constraints: Can be positive, negative, or zero
  • Example: 100.0, -50.5, 0.0

volume

  • Type: Positive number (float or int)
  • Required: Yes
  • Constraints: Must be > 0
  • Example: 1.0, 0.5

date

  • Type: String
  • Format: YYYY-MM-DD
  • Required: Yes
  • Constraints: Must be a future date
  • Example: "2024-01-15"

start_time / end_time

  • Type: String
  • Format: HH:MM (24-hour)
  • Required: Yes
  • Constraints:
    • Must be future times
    • end_time must be after start_time
  • Example: "14:00", "15:30"

duration

  • Type: String
  • Required: Yes
  • Common values: "15m", "30m", "1h", "4h"
  • Example: "15m" (15 minutes)

tz_offset_hours

  • Type: Integer
  • Required: No (auto-detected if not provided)
  • Range: Typically -12 to +14
  • Example: 0 (UTC), 1 (UTC+1), -5 (UTC-5)
  • Note: If not provided, the system will auto-detect your timezone

state

  • Type: String
  • Required: No (defaults to "displayed")
  • Values: "displayed" or "hidden"
  • Description: Controls order visibility. A "displayed" order is visible on the market, while a "hidden" order is not shown to other participants.
  • Example: "displayed", "hidden"

options

  • Type: Dict (optional)
  • Required: No
  • Description: Additional order options passed to the API. Internal use only (Groupe-E).
  • Fields:
    • trader_suffixe (str, optional): Suffix appended to the trader name (e.g. Hermes becomes Hermes_my_bot). Max 50 characters. Only available for Groupe-E accounts.
  • Example: {"trader_suffixe": "my_bot"}, None, {}
  • Note: This option is ignored for non Groupe-E accounts.

Complete Order Examples

Valid Buy Order (displayed)

buy_order = {
    "side": "buy",
    "price": 150.25,
    "volume": 2.5,
    "date": "2024-12-15",
    "start_time": "14:00",
    "end_time": "14:15", 
    "duration": "15m",
    "tz_offset_hours": 1,  # CET (UTC+1)
    "state": "displayed"   # Visible on the market (default)
}

Valid Sell Order (hidden)

sell_order = {
    "side": "sell",
    "price": 200.0,
    "volume": 1.0,
    "date": "2024-12-15",
    "start_time": "15:30",
    "end_time": "16:00",
    "duration": "30m", 
    "tz_offset_hours": 0,  # UTC
    "state": "hidden"      # Hidden from other participants
}

Time Validation Rules

  1. Date must be in the future - Past dates will be rejected
  2. Times must be in the future - Current time already passed will be rejected
  3. End time > Start time - Duration must be positive
  4. Duration should match time window - (end_time - start_time) should equal duration

Common Validation Errors

# ❌ Missing required field
{"side": "buy", "price": 100}  # Missing volume, date, etc.

# ❌ Invalid side
{"side": "invalid", ...}  # Must be "buy" or "sell"

# ❌ Negative price/volume  
{"side": "buy", "price": -10, "volume": 1.0, ...}  # Negative prices are now allowed!

# ❌ Negative volume
{"side": "buy", "price": 100, "volume": -1.0, ...}  # Volume must still be positive

# ❌ Past date
{"side": "buy", "date": "2020-01-01", ...}

# ❌ Invalid time format
{"side": "buy", "start_time": "2:00 PM", ...}  # Must be HH:MM

# ❌ End time before start time
{"side": "buy", "start_time": "15:00", "end_time": "14:00", ...}

# ❌ Invalid state
{"side": "buy", "state": "invisible", ...}  # Must be "displayed" or "hidden"

Bulk Orders Format

bulk_orders = {
    "orders": [
        # Order 1 - displayed (default)
        {
            "side": "buy",
            "price": 100.0,
            "volume": 1.0,
            "date": "2024-12-15",
            "start_time": "14:00",
            "end_time": "14:15",
            "duration": "15m",
            "tz_offset_hours": 0
        },
        # Order 2 - hidden
        {
            "side": "sell",
            "price": 200.0,
            "volume": 0.5,
            "date": "2024-12-15", 
            "start_time": "14:30",
            "end_time": "15:00",
            "duration": "30m",
            "tz_offset_hours": 0,
            "state": "hidden"
        },
        # ... more orders (up to API limits)
    ]
}

Helper Function for Order Creation

from datetime import datetime, timedelta

def create_order_data(side, price, volume, hours_in_future=4):
    """Helper to create valid order data"""
    future_time = datetime.now() + timedelta(hours=hours_in_future)
    
    # Round to next quarter hour
    minutes = future_time.minute
    if minutes < 15:
        future_time = future_time.replace(minute=15, second=0, microsecond=0)
    elif minutes < 30:
        future_time = future_time.replace(minute=30, second=0, microsecond=0)
    elif minutes < 45:
        future_time = future_time.replace(minute=45, second=0, microsecond=0)
    else:
        future_time = future_time.replace(minute=0, second=0, microsecond=0) + timedelta(hours=1)
    
    future_end = future_time + timedelta(minutes=15)
    
    return {
        "side": side,
        "price": float(price),
        "volume": float(volume),
        "date": future_time.strftime("%Y-%m-%d"),
        "start_time": future_time.strftime("%H:%M"),
        "end_time": future_end.strftime("%H:%M"),
        "duration": "15m",
        "tz_offset_hours": 0,
        "state": "displayed"  # or "hidden"
    }

# Usage
order = create_order_data("buy", 100.0, 1.0)
result = await api.create_order(order)

Response Formats

Order Creation Response

# Single order
{
    "order_id": "ord_abc123",
    "created_at": "2024-01-15T14:00:00Z",
    "direction": "buy",
    "volume": 1.0,
    "price": 100.0,
    "state": "Displayed",
    "contract": "BASE-QUOTE",
    "trader": "your_trader_name",
    "date": "2024-01-15",
    "start_time": "14:00",
    "end_time": "14:15",
    "duration": "15m",
    "tz_offset_hours": 0,
    "updated_at": "2024-01-15T14:00:00Z"
}

# Bulk orders
{
    "requested": 2,
    "created": [
        {
            "index": 0,
            "result": {
                "order_id": "ord_abc123",
                "created_at": "2024-01-15T14:00:00Z",
                "direction": "buy",
                "volume": 1.0,
                "price": 100.0,
                "state": "Displayed",
                "contract": "BASE-QUOTE",
                "trader": "your_trader_name",
                "date": "2024-01-15",
                "start_time": "14:00",
                "end_time": "14:15",
                "duration": "15m",
                "tz_offset_hours": 0,
                "updated_at": "2024-01-15T14:00:00Z"
            }
        },
        {
            "index": 1,
            "result": {
                "order_id": "ord_def456",
                "created_at": "2024-01-15T14:00:00Z",
                "direction": "sell",
                "volume": 0.5,
                "price": 200.0,
                "state": "Displayed",
                "contract": "BASE-QUOTE",
                "trader": "your_trader_name",
                "date": "2024-01-15",
                "start_time": "14:30",
                "end_time": "15:00",
                "duration": "30m",
                "tz_offset_hours": 0,
                "updated_at": "2024-01-15T14:00:00Z"
            }
        }
    ],
    "failed": [
        {
            "index": 2,
            "error": "Invalid price: must be positive number"
        }
    ]
}

Order Data (from get_orders)

{
    "order_id": 1234,                    # Numeric ID for deletion
    "direction": "buy",                  # "buy" or "sell"
    "volume": 1.0,                       # Order volume
    "price": 100.0,                      # Order price
    "state": "Displayed",                 # Order state
    "contract": "BASE-QUOTE",             # Trading pair
    "trader": "your_trader_name",         # Trader identifier
    "date": "2024-01-15",                # Order date
    "start_time": "14:00",               # Start time
    "end_time": "14:15",                 # End time
    "duration": "15m",                   # Duration
    "tz_offset_hours": 0,                # Timezone offset
    "created_at": "2024-01-15T14:00:00Z", # Creation timestamp
    "updated_at": "2024-01-15T14:00:00Z", # Last update timestamp
    "executed_volume": 0.0,              # Volume already executed (if any)
    "remaining_volume": 1.0,             # Volume remaining to execute
    "average_price": null,               # Average execution price (if executed)
    "execution_count": 0,                # Number of executions
    "total_value": 100.0,                # Total order value (volume × price)
    "metadata": {}                       # Additional metadata
}

Market Data Response

[
    {
        "timestamp": "2024-01-15T14:00:00Z",
        "contract": "BASE-QUOTE",
        "price": 100.5,
        "volume": 1500.0,
        "bid": 100.4,
        "ask": 100.6,
        "spread": 0.2,
        "high_24h": 105.0,
        "low_24h": 95.0,
        "volume_24h": 50000.0,
        "change_24h": 2.5,
        "change_percent_24h": 2.56
    }
]

Trades Data Response

[
    {
        "trade_id": "trade_abc123",
        "contract": "BASE-QUOTE",
        "direction": "buy",
        "volume": 1.0,
        "price": 100.5,
        "timestamp": "2024-01-15T14:00:00Z",
        "buyer": "buyer_name",
        "seller": "seller_name",
        "duration": "15m",
        "execution_time": "2024-01-15T14:07:30Z"
    }
]

LTP (Last Traded Price) Response

[
    {
        "market_zone": "10YCH-SWISSGRIDZ",
        "contract": "2025-01-15T14:00:00Z/PT15M",
        "price": 100.5,
        "volume": 1500.0,
        "timestamp": "2024-01-15T14:00:00Z"
    },
    {
        "market_zone": "10YDE-RWENET---I",
        "contract": "2025-01-15T14:00:00Z/PT15M",
        "price": 98.25,
        "volume": 2000.0,
        "timestamp": "2024-01-15T14:00:00Z"
    }
]

Latest LTP by Contract Response

{
    "2025-01-15T14:00:00Z/PT15M": {
        "price": 100.5,
        "volume": 1500.0,
        "timestamp": "2024-01-15T14:00:00Z",
        "market_zones": ["10YCH-SWISSGRIDZ", "10YDE-RWENET---I"],
        "latest_zone": "10YCH-SWISSGRIDZ"
    },
    "2025-01-15T14:15:00Z/PT15M": {
        "price": 98.0,
        "volume": 2000.0,
        "timestamp": "2024-01-15T14:05:00Z",
        "market_zones": ["10YCH-SWISSGRIDZ"],
        "latest_zone": "10YCH-SWISSGRIDZ"
    }
}

Spot Data Response

{
    "contract": "BASE-QUOTE",
    "price": 100.5,
    "volume": 1500.0,
    "bid": 100.4,
    "ask": 100.6,
    "spread": 0.2,
    "high_24h": 105.0,
    "low_24h": 95.0,
    "volume_24h": 50000.0,
    "change_24h": 2.5,
    "change_percent_24h": 2.56,
    "timestamp": "2024-01-15T14:00:00Z",
    "order_book": {
        "bids": [
            {"price": 100.4, "volume": 500.0},
            {"price": 100.3, "volume": 300.0}
        ],
        "asks": [
            {"price": 100.6, "volume": 400.0},
            {"price": 100.7, "volume": 200.0}
        ]
    }
}

API Status Response

{
    "status": "healthy",
    "version": "1.2.3",
    "timestamp": "2024-01-15T14:00:00Z",
    "services": {
        "orders": "operational",
        "trades": "operational", 
        "market_data": "operational",
        "spot": "operational"
    },
    "uptime": 86400,
    "response_time_ms": 45,
    "rate_limit": {
        "requests_per_minute": 1000,
        "requests_remaining": 999,
        "reset_time": "2024-01-15T14:01:00Z"
    }
}

Spot Status Response

{
    "status": "operational",
    "timestamp": "2024-01-15T14:00:00Z",
    "active_contracts": ["BASE-QUOTE", "OTHER-PAIR"],
    "market_open": true,
    "next_update": "2024-01-15T14:01:00Z",
    "last_update": "2024-01-15T13:59:00Z"
}

Error Handling

The client provides comprehensive error handling:

GameAPIError

All API errors raise GameAPIError with descriptive messages:

from game_client import GameAPI, GameAPIError

async def example():
    api = GameAPI(token="token", base_url="https://api.example.com")
    
    try:
        await api.create_order({"invalid": "data"})
    except GameAPIError as e:
        print(f"API Error: {e}")
        # Output: "API Error: Single order: Missing required field 'side'"

Common Errors

  • Authentication: Invalid token or connection issues
  • Validation: Missing required fields or invalid values
  • Not Found: Order ID doesn't exist
  • Network: Connection timeout or server errors

Best Practices

  1. Always handle errors
try:
    result = await api.create_order(order_data)
except GameAPIError as e:
    logger.error(f"Order creation failed: {e}")
    return None
  1. Test connection first
if not await api.test_connection():
    print("Cannot connect to API")
    return
  1. Use find_order_by_id for safe lookups
order = await api.find_order_by_id(order_id)
if order is None:
    print("Order not found")
else:
    print(f"Found: {order}")
  1. Validate order data before sending
# The client validates automatically, but you can pre-validate
required_fields = ["side", "price", "volume", "date", "start_time", "end_time"]
for field in required_fields:
    if field not in order_data:
        raise ValueError(f"Missing required field: {field}")

Advanced Usage

Custom Timeout and SSL

api = GameAPI(
    token="your_token",
    base_url="https://api.example.com",
    verify_ssl=True,        # Enable SSL verification (production)
    timeout=60              # Custom timeout in seconds
)

Bulk Operations

# Create multiple orders efficiently
bulk_orders = {
    "orders": [
        {"side": "buy", "price": 100, "volume": 1, ...},
        {"side": "sell", "price": 200, "volume": 0.5, ...},
        # ... up to 100 orders
    ]
}

result = await api.create_order(bulk_orders)
print(f"Created: {len(result['created'])}, Failed: {len(result['failed'])}")

Rate Limiting

The client handles rate limiting automatically through token management, but you should implement your own rate limiting for bulk operations:

import asyncio

async def safe_bulk_create(api, orders_list, batch_size=10):
    """Create orders in batches to avoid rate limits"""
    results = []
    
    for i in range(0, len(orders_list), batch_size):
        batch = orders_list[i:i + batch_size]
        bulk_data = {"orders": batch}
        
        try:
            result = await api.create_order(bulk_data)
            results.extend(result.get('created', []))
            
            # Small delay between batches
            if i + batch_size < len(orders_list):
                await asyncio.sleep(1)
                
        except GameAPIError as e:
            print(f"Batch {i//batch_size + 1} failed: {e}")
    
    return results

Testing

# Install dependencies
pip install -r requirements.txt
pip install -e .

# Install test dependencies
pip install pytest pytest-asyncio pytest-cov

# Run tests
pytest tests/ -v --cov=game_client

Docker

# Build
docker build -f Dockerfile.demo -t game-api-client .

# Option 1: Run with environment variables (recommended for production)
docker run --rm \
  -e GAME_API_TOKEN="your_token" \
  -e GAME_API_URL="https://your-game-api-url.com" \
  -e GAME_API_VERIFY_SSL=false \
  game-api-client

# Option 2: Run with .env file (for development)
docker run --rm \
  -v $(pwd)/.env:/app/.env:ro \
  game-api-client

# Option 3: Run with custom command
docker run --rm \
  -e GAME_API_TOKEN="your_token" \
  -e GAME_API_URL="https://your-game-api-url.com" \
  -e GAME_API_VERIFY_SSL=false \
  game-api-client python example.py

Development

# Setup development environment
poetry install

# Run example
python example.py

# Run tests
poetry run pytest tests/ -v

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

game_api_client-0.1.0.tar.gz (19.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

game_api_client-0.1.0-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

Details for the file game_api_client-0.1.0.tar.gz.

File metadata

  • Download URL: game_api_client-0.1.0.tar.gz
  • Upload date:
  • Size: 19.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for game_api_client-0.1.0.tar.gz
Algorithm Hash digest
SHA256 64139ae1648c801ec1fd8b5c4e9518b95cff570d0cc61d24df9923575e44e29f
MD5 b6095d8d6e9637f7ace6c7a720970da3
BLAKE2b-256 b26f9a4c6f278fa586e552ca6b14da6183f9da1de2a38ff5e3b1baeb00445c6b

See more details on using hashes here.

File details

Details for the file game_api_client-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for game_api_client-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9cc73115e7c6e71b0f7a04a465e7346f175fdd887d7f980d0c400144c4e06670
MD5 ce4895c728989f1ff3821fc67769df18
BLAKE2b-256 629d815446a39c9ff5be51adf072754abac19147eec4091caa6ce2cab2d23878

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