> For the complete documentation index, see [llms.txt](https://docs.gameket.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gameket.io/examples/python.md).

# Python

#### Basic Setup

{% code expandable="true" %}

```python
import requests
import os
from datetime import datetime, timedelta
import json

class GametekMerchantAPI:
    def __init__(self, api_key, secret, base_url='https://api.gameket.io'):
        self.api_key = api_key
        self.secret = secret
        self.base_url = base_url
        self.token = None
        self.token_expires_at = None

    def get_token(self):
        """Get or refresh access token"""
        if self.token and datetime.now() < self.token_expires_at - timedelta(seconds=60):
            return self.token

        response = requests.post(
            f'{self.base_url}/merchant/auth/check',
            json={
                'apiKey': self.api_key,
                'secret': self.secret
            }
        )
        response.raise_for_status()

        data = response.json()['data']
        self.token = data['token']
        self.token_expires_at = datetime.fromisoformat(
            data['expiresAt'].replace('Z', '+00:00')
        )

        return self.token

    def request(self, method, endpoint, json_body=None, **kwargs):
        """Make authenticated API request"""
        token = self.get_token()
        headers = {
            'Authorization': f'Bearer {token}',
            'x-merchant-api-key': self.api_key,
            'Content-Type': 'application/json'
        }
        headers.update(kwargs.get('headers', {}))

        response = requests.request(
            method,
            f'{self.base_url}{endpoint}',
            json=json_body,
            headers=headers,
            **{k: v for k, v in kwargs.items() if k != 'headers'}
        )
        response.raise_for_status()

        return response.json()

    def get_profile(self):
        """Get merchant profile"""
        return self.request('GET', '/merchant')

    def list_orders(self, page=1, limit=20, **filters):
        """List orders with optional filters"""
        params = {'page': page, 'limit': limit, **filters}
        params_str = '&'.join(f'{k}={v}' for k, v in params.items())
        return self.request('GET', f'/merchant/orders?{params_str}')

    def create_product(self, product_data):
        """Create new product"""
        return self.request('POST', '/merchant/products', product_data)

    def deliver_codes(self, order_id, codes):
        """Deliver codes to fulfill order"""
        return self.request(
            'POST',
            f'/merchant/orders/codes?orderId={order_id}',
            {'codes': codes},
            headers={'Idempotency-Key': f'deliver-{order_id}'}
        )

    def refund_order(self, order_id, reason, amount):
        """Refund an order"""
        return self.request(
            'POST',
            f'/merchant/orders/refund?orderId={order_id}',
            {'reason': reason, 'amount': amount},
            headers={'Idempotency-Key': f'refund-{order_id}'}
        )

# Usage
client = GametekMerchantAPI(
    os.getenv('MERCHANT_API_KEY'),
    os.getenv('MERCHANT_SECRET')
)

# Get profile
profile = client.get_profile()
print(f"Welcome {profile['data']['storeName']}")

# List orders
orders = client.list_orders(page=1, limit=50, status='pending')
print(f"Found {len(orders['data'])} pending orders")

# Deliver codes for first order
if orders['data']:
    order = orders['data'][0]
    codes = ['CODE-001', 'CODE-002']
    result = client.deliver_codes(order['orderId'], codes)
    print(f"Delivered codes to order {order['orderId']}")
```

{% endcode %}
