# Code Examples

This section provides complete, copy-pastable code examples for interacting with the ForePaaS API in various programming languages. Each example includes full error handling and best practices.

## SDK Client Implementation

Below are complete SDK client implementations you can use in your applications.

{% tabs %}
{% tab title="Node.js" %}

```javascript
// foregate-client.js
const crypto = require('crypto');
const fetch = require('node-fetch');

class ForegateClient {
  constructor(apiKey, privateKey, baseUrl = 'https://apidev.forepass.org') {
    this.apiKey = apiKey;
    this.privateKey = privateKey;
    this.baseUrl = baseUrl;
    this.jwtToken = null;
  }

  // Generate RSA-SHA256 signature
  generateSignature(method, path, body, timestamp, nonce) {
    const contentType = 'application/json';
    const bodyString = body ? JSON.stringify(body) : '';
    
    const signContent = [
      method,
      contentType,
      path,
      bodyString,
      timestamp.toString(),
      nonce
    ].join('\n');

    const sign = crypto.createSign('SHA256');
    sign.update(signContent);
    sign.end();

    return sign.sign(this.privateKey, 'base64');
  }

  // Make authenticated request
  async request(method, path, body = null, useJWT = false) {
    const timestamp = Date.now();
    const nonce = crypto.randomBytes(16).toString('hex');
    
    const headers = {
      'Content-Type': 'application/json'
    };

    if (useJWT && this.jwtToken) {
      headers['Authorization'] = `Bearer ${this.jwtToken}`;
    } else {
      const signature = this.generateSignature(method, path, body, timestamp, nonce);
      headers['X-API-KEY'] = this.apiKey;
      headers['X-Signature'] = signature;
      headers['X-Timestamp'] = timestamp.toString();
      headers['X-Nonce'] = nonce;
    }

    const options = {
      method,
      headers
    };

    if (body) {
      options.body = JSON.stringify(body);
    }

    const response = await fetch(`${this.baseUrl}${path}`, options);
    const data = await response.json();

    if (data.code !== 200) {
      throw new Error(`API Error ${data.code}: ${data.msg}`);
    }

    return data;
  }

  // Authorize user and get JWT token
  async authorizeUser(merchantUserId, userEmail, options = {}) {
    const body = {
      marchantUserId: merchantUserId,
      userEmail: userEmail,
      ...options
    };

    const data = await this.request('POST', '/api/user/openapi/authorize', body);
    this.jwtToken = data.data.token;
    return data.data;
  }

  // Get market list
  async getMarkets(params = {}) {
    const queryString = new URLSearchParams(params).toString();
    const path = `/api/market/openapi/market/list?${queryString}`;
    return await this.request('GET', path);
  }

  // Get market details
  async getMarketDetails(marketId) {
    const path = `/api/market/openapi/${marketId}/outcome`;
    return await this.request('GET', path);
  }

  // Submit order
  async submitOrder(orderData) {
    return await this.request('POST', '/api/order/openapi/order/submit', orderData, true);
  }

  // Get user positions
  async getUserPositions(marketId = null, page = 1, pageSize = 10) {
    const body = { page, pageSize };
    if (marketId) {
      body.marketId = marketId;
    }
    return await this.request('POST', '/api/order/openapi/positions', body, true);
  }

  // Claim rewards
  async claimRewards(marketId) {
    return await this.request('POST', '/api/order/openapi/order/claim', { marketId }, true);
  }

  // Query merchant monthly bill
  async getMonthlyBill(billPeriod, merchantId) {
    return await this.request('POST', '/api/order/openapi/merchant-commission-bill/query/month', 
      { billPeriod, merchantId }, true);
  }

  // Query merchant user bill details
  async getUserBillDetails(merchantId, merchantUserId) {
    const queryString = new URLSearchParams({ merchantId, merchantUserId }).toString();
    const path = `/api/order/openapi/bill/query-detail?${queryString}`;
    return await this.request('GET', path, null, true);
  }
}

module.exports = ForegateClient;
```

{% endtab %}

{% tab title="Python" %}

```python
# foregate_client.py
import base64
import hashlib
import json
import time
import secrets
from typing import Dict, Optional, Any
import requests
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend

class ForegateClient:
    def __init__(self, api_key: str, private_key_pem: str, 
                 base_url: str = 'https://apidev.forepass.org'):
        self.api_key = api_key
        self.private_key = serialization.load_pem_private_key(
            private_key_pem.encode(),
            password=None,
            backend=default_backend()
        )
        self.base_url = base_url
        self.jwt_token = None

    def generate_signature(self, method: str, path: str, 
                          body: Optional[Dict], timestamp: int, nonce: str) -> str:
        """Generate RSA-SHA256 signature"""
        content_type = 'application/json'
        body_string = json.dumps(body) if body else ''
        
        sign_content = '\n'.join([
            method,
            content_type,
            path,
            body_string,
            str(timestamp),
            nonce
        ])

        signature = self.private_key.sign(
            sign_content.encode('utf-8'),
            padding.PKCS1v15(),
            hashes.SHA256()
        )

        return base64.b64encode(signature).decode('utf-8')

    def request(self, method: str, path: str, 
                body: Optional[Dict] = None, use_jwt: bool = False) -> Dict[str, Any]:
        """Make authenticated request"""
        timestamp = int(time.time() * 1000)
        nonce = secrets.token_hex(16)
        
        headers = {
            'Content-Type': 'application/json'
        }

        if use_jwt and self.jwt_token:
            headers['Authorization'] = f'Bearer {self.jwt_token}'
        else:
            signature = self.generate_signature(method, path, body, timestamp, nonce)
            headers.update({
                'X-API-KEY': self.api_key,
                'X-Signature': signature,
                'X-Timestamp': str(timestamp),
                'X-Nonce': nonce
            })

        url = f'{self.base_url}{path}'
        
        if method == 'GET':
            response = requests.get(url, headers=headers)
        elif method == 'POST':
            response = requests.post(url, headers=headers, json=body)
        elif method == 'PUT':
            response = requests.put(url, headers=headers, json=body)
        else:
            raise ValueError(f'Unsupported method: {method}')

        data = response.json()

        if data['code'] != 200:
            raise Exception(f"API Error {data['code']}: {data['msg']}")

        return data

    def authorize_user(self, merchant_user_id: str, user_email: str, **kwargs) -> Dict:
        """Authorize user and get JWT token"""
        body = {
            'marchantUserId': merchant_user_id,
            'userEmail': user_email,
            **kwargs
        }

        data = self.request('POST', '/api/user/openapi/authorize', body)
        self.jwt_token = data['data']['token']
        return data['data']

    def get_markets(self, **params) -> Dict:
        """Get market list"""
        query_string = '&'.join([f'{k}={v}' for k, v in params.items()])
        path = f'/api/market/openapi/market/list?{query_string}'
        return self.request('GET', path)

    def get_market_details(self, market_id: int) -> Dict:
        """Get market details"""
        path = f'/api/market/openapi/{market_id}/outcome'
        return self.request('GET', path)

    def submit_order(self, order_data: Dict) -> Dict:
        """Submit order"""
        return self.request('POST', '/api/order/openapi/order/submit', order_data, use_jwt=True)

    def get_user_positions(self, market_id: int = None, page: int = 1, page_size: int = 10) -> Dict:
        """Get user positions"""
        body = {
            'page': page,
            'pageSize': page_size
        }
        if market_id:
            body['marketId'] = market_id
        return self.request('POST', '/api/order/openapi/positions', body, use_jwt=True)

    def claim_rewards(self, market_id: int) -> Dict:
        """Claim rewards"""
        return self.request('POST', '/api/order/openapi/order/claim', 
                          {'marketId': market_id}, use_jwt=True)

    def get_monthly_bill(self, bill_period: int, merchant_id: int) -> Dict:
        """Query merchant monthly bill"""
        return self.request('POST', '/api/order/openapi/merchant-commission-bill/query/month',
                          {'billPeriod': bill_period, 'merchantId': merchant_id}, use_jwt=True)

    def get_user_bill_details(self, merchant_id: int, merchant_user_id: str) -> Dict:
        """Query merchant user bill details"""
        query_string = f'merchantId={merchant_id}&merchantUserId={merchant_user_id}'
        path = f'/api/order/openapi/bill/query-detail?{query_string}'
        return self.request('GET', path, use_jwt=True)
```

{% endtab %}
{% endtabs %}

## End-to-End Workflows

### Order Submission Flow

Here's a complete order submission workflow:

| Step | Actor | Action                             | API Call                                               | Result                                       |
| ---- | ----- | ---------------------------------- | ------------------------------------------------------ | -------------------------------------------- |
| 1    | User  | Opens app and wants to place order | -                                                      | -                                            |
| 2    | App   | Authenticate user                  | `POST /api/user/openapi/authorize`                     | JWT Token received                           |
| 3    | App   | Fetch market details               | `GET /api/market/openapi/{id}/outcome`                 | Current prices and market info               |
| 4    | App   | Display market to user             | -                                                      | User sees: YES @ $0.65, NO @ $0.35           |
| 5    | User  | Confirms order: 100 shares @ $0.65 | -                                                      | -                                            |
| 6    | App   | Submit order                       | `POST /api/order/openapi/order/submit`                 | Order processing...                          |
| 7a   | API   | ✅ **Success Path**                 | Validate balance → Check market status → Execute order | Return `200` with `fgRequestId`              |
| 7b   | API   | ❌ **Insufficient Balance**         | Balance check fails                                    | Return `422 Insufficient balance`            |
| 7c   | API   | ❌ **Market Closed**                | Market status check fails                              | Return `422 Market closed`                   |
| 8a   | App   | Show success to user               | -                                                      | "✓ Order confirmed! Request ID: d7c19300..." |
| 8b   | App   | Show error to user                 | -                                                      | "✗ Please add funds to your account"         |
| 8c   | App   | Show error to user                 | -                                                      | "✗ Market no longer accepting trades"        |

**Key Validations:**

* User balance must be sufficient for the order
* Market must be in `ACTIVE` status
* Price must be current (fetch latest before submitting)
* JWT token must be valid and not expired

### Workflow 1: User Authentication

{% tabs %}
{% tab title="Node.js" %}

```javascript
const ForegateClient = require('./foregate-client');

async function authenticateUser() {
  // Initialize client
  const client = new ForegateClient(
    'your-api-key',
    `-----BEGIN PRIVATE KEY-----
    Your Private Key Here
    -----END PRIVATE KEY-----`
  );

  try {
    // Authorize user
    const user = await client.authorizeUser(
      'user123',
      'user123@example.com',
      {
        userType: 'creator',
        coinType: 'crypto',
        currency: 'USDT'
      }
    );

    console.log('User authenticated:', user);
    console.log('JWT Token:', user.token);
    
    return client;
  } catch (error) {
    console.error('Authentication failed:', error.message);
    throw error;
  }
}

authenticateUser();
```

{% endtab %}

{% tab title="Python" %}

```python
from foregate_client import ForegateClient

def authenticate_user():
    # Initialize client
    client = ForegateClient(
        api_key='your-api-key',
        private_key_pem='''-----BEGIN PRIVATE KEY-----
        Your Private Key Here
        -----END PRIVATE KEY-----'''
    )

    try:
        # Authorize user
        user = client.authorize_user(
            merchant_user_id='user123',
            user_email='user123@example.com',
            userType='creator',
            coinType='crypto',
            currency='USDT'
        )

        print(f'User authenticated: {user}')
        print(f'JWT Token: {user["token"]}')
        
        return client
    except Exception as e:
        print(f'Authentication failed: {e}')
        raise

if __name__ == '__main__':
    authenticate_user()
```

{% endtab %}
{% endtabs %}

### Workflow 2: Browse and View Markets

{% tabs %}
{% tab title="Node.js" %}

```javascript
async function browseMarkets(client) {
  try {
    // Get markets with trending sort
    const markets = await client.getMarkets({
      page: 1,
      pageSize: 20,
      sortBy: 'Trending'
    });

    console.log(`Found ${markets.total} markets`);

    // Get details for the first market
    if (markets.data.length > 0) {
      const marketId = markets.data[0].marketId;
      const details = await client.getMarketDetails(marketId);
      
      console.log('Market Details:', details.data);
      console.log('Outcomes:');
      
      details.data.outcomes.forEach(outcome => {
        outcome.options.forEach(option => {
          console.log(`  ${option.title}: $${option.price}`);
        });
      });
    }
  } catch (error) {
    console.error('Error browsing markets:', error.message);
  }
}
```

{% endtab %}

{% tab title="Python" %}

```python
def browse_markets(client: ForegateClient):
    try:
        # Get markets with trending sort
        markets = client.get_markets(
            page=1,
            pageSize=20,
            sortBy='Trending'
        )

        print(f"Found {markets['total']} markets")

        # Get details for the first market
        if markets['data']:
            market_id = markets['data'][0]['marketId']
            details = client.get_market_details(market_id)
            
            print(f"Market Details: {details['data']}")
            print('Outcomes:')
            
            for outcome in details['data']['outcomes']:
                for option in outcome['options']:
                    print(f"  {option['title']}: ${option['price']}")
                    
    except Exception as e:
        print(f'Error browsing markets: {e}')
```

{% endtab %}
{% endtabs %}

### Workflow 3: Place an Order

{% tabs %}
{% tab title="Node.js" %}

```javascript
async function placeOrder(client) {
  try {
    // First, get market details to find current prices
    const marketId = 1744;
    const details = await client.getMarketDetails(marketId);
    
    const yesOption = details.data.outcomes[0].options[0];
    
    // Place a market buy order
    const order = await client.submitOrder({
      marketId: marketId,
      outcomeId: details.data.outcomes[0].outcomeId,
      optionId: yesOption.optionId,
      chooseOutcome: 'YES',
      direction: 'BUY',
      orderType: 'MARKET',
      price: yesOption.price,
      shares: 100
    });

    console.log('Order placed successfully:', order.data);
    console.log('Order ID:', order.data.orderId);
    console.log('Status:', order.data.status);
    
  } catch (error) {
    console.error('Order failed:', error.message);
  }
}
```

{% endtab %}

{% tab title="Python" %}

```python
def place_order(client: ForegateClient):
    try:
        # First, get market details to find current prices
        market_id = 1744
        details = client.get_market_details(market_id)
        
        yes_option = details['data']['outcomes'][0]['options'][0]
        
        # Place a market buy order
        order = client.submit_order({
            'marketId': market_id,
            'outcomeId': details['data']['outcomes'][0]['outcomeId'],
            'optionId': yes_option['optionId'],
            'chooseOutcome': 'YES',
            'direction': 'BUY',
            'orderType': 'MARKET',
            'price': yes_option['price'],
            'shares': 100
        })

        print(f"Order placed successfully: {order['data']}")
        print(f"Order ID: {order['data']['orderId']}")
        print(f"Status: {order['data']['status']}")
        
    except Exception as e:
        print(f'Order failed: {e}')
```

{% endtab %}
{% endtabs %}

### Workflow 4: Check Positions and Claim Rewards

{% tabs %}
{% tab title="Node.js" %}

```javascript
async function checkPositionsAndClaim(client, userId) {
  try {
    // Get user positions
    const positions = await client.getUserPositions(1744, userId);
    
    console.log(`You have ${positions.data.length} position(s)`);
    
    positions.data.forEach(position => {
      console.log(`\nMarket: ${position.marketTitle}`);
      console.log(`  Position: ${position.optionTitle}`);
      console.log(`  Shares: ${position.shares}`);
      console.log(`  Cost: $${position.costValue}`);
      console.log(`  Current Value: $${position.currentValue}`);
      console.log(`  P&L: $${position.pnl} (${(position.pnl / position.costValue * 100).toFixed(2)}%)`);
      
      // If market is settled and we won, claim rewards
      if (position.orderStatus === 'SETTLED' && position.pnl > 0) {
        console.log('  Claiming rewards...');
        
        client.claimRewards(position.marketId)
          .then(result => {
            console.log(`  Claimed $${result.data.claimedAmount}!`);
          })
          .catch(err => {
            console.error(`  Claim failed: ${err.message}`);
          });
      }
    });
    
  } catch (error) {
    console.error('Error checking positions:', error.message);
  }
}
```

{% endtab %}

{% tab title="Python" %}

```python
def check_positions_and_claim(client: ForegateClient, user_id: str):
    try:
        # Get user positions
        positions = client.get_user_positions(1744, user_id)
        
        print(f"You have {len(positions['data'])} position(s)")
        
        for position in positions['data']:
            print(f"\nMarket: {position['marketTitle']}")
            print(f"  Position: {position['optionTitle']}")
            print(f"  Shares: {position['shares']}")
            print(f"  Cost: ${position['costValue']}")
            print(f"  Current Value: ${position['currentValue']}")
            pnl_pct = (position['pnl'] / position['costValue'] * 100)
            print(f"  P&L: ${position['pnl']} ({pnl_pct:.2f}%)")
            
            # If market is settled and we won, claim rewards
            if position['orderStatus'] == 'SETTLED' and position['pnl'] > 0:
                print('  Claiming rewards...')
                
                try:
                    result = client.claim_rewards(position['marketId'])
                    print(f"  Claimed ${result['data']['claimedAmount']}!")
                except Exception as e:
                    print(f"  Claim failed: {e}")
                    
    except Exception as e:
        print(f'Error checking positions: {e}')
```

{% endtab %}
{% endtabs %}

### Complete Application Example

{% tabs %}
{% tab title="Node.js" %}

```javascript
const ForegateClient = require('./foregate-client');

async function main() {
  // Initialize client
  const client = new ForegateClient(
    process.env.FOREPAAS_API_KEY,
    process.env.FOREPAAS_PRIVATE_KEY
  );

  try {
    // Step 1: Authenticate user
    console.log('=== Step 1: Authentication ===');
    const user = await client.authorizeUser(
      'user123',
      'user123@example.com'
    );
    console.log(`✓ Authenticated as user ${user.id}`);

    // Step 2: Browse markets
    console.log('\n=== Step 2: Browse Markets ===');
    const markets = await client.getMarkets({
      page: 1,
      pageSize: 5,
      sortBy: 'Trending'
    });
    console.log(`✓ Found ${markets.total} live markets`);

    // Step 3: Get market details
    if (markets.data.length > 0) {
      console.log('\n=== Step 3: Market Details ===');
      const marketId = markets.data[0].marketId;
      const details = await client.getMarketDetails(marketId);
      console.log(`✓ Market: ${details.data.title}`);
      console.log(`  Volume: $${details.data.volume}`);

      // Step 4: Place an order
      console.log('\n=== Step 4: Place Order ===');
      const order = await client.submitOrder({
        marketId: marketId,
        outcomeId: details.data.outcomes[0].outcomeId,
        optionId: details.data.outcomes[0].options[0].optionId,
        direction: 'BUY',
        orderType: 'PARIMUTUEL',
        amount: 10
      });
      console.log(`✓ Order placed: ${order.data.fgRequestId}`);

      // Step 5: Check positions
      console.log('\n=== Step 5: Check Positions ===');
      const positions = await client.getUserPositions(marketId, 1, 10);
      console.log(`✓ You have ${positions.data.length} position(s) in this market`);
    }

    console.log('\n✓ All operations completed successfully!');

  } catch (error) {
    console.error('Error:', error.message);
    process.exit(1);
  }
}

main();
```

{% endtab %}

{% tab title="Python" %}

```python
import os
from foregate_client import ForegateClient

def main():
    # Initialize client
    client = ForegateClient(
        api_key=os.getenv('FOREPAAS_API_KEY'),
        private_key_pem=os.getenv('FOREPAAS_PRIVATE_KEY')
    )

    try:
        # Step 1: Authenticate user
        print('=== Step 1: Authentication ===')
        user = client.authorize_user(
            merchant_user_id='user123',
            user_email='user123@example.com'
        )
        print(f"✓ Authenticated as user {user['id']}")

        # Step 2: Browse markets
        print('\n=== Step 2: Browse Markets ===')
        markets = client.get_markets(
            page=1,
            pageSize=5,
            sortBy='Trending'
        )
        print(f"✓ Found {markets['total']} live markets")

        # Step 3: Get market details
        if markets['data']:
            print('\n=== Step 3: Market Details ===')
            market_id = markets['data'][0]['marketId']
            details = client.get_market_details(market_id)
            print(f"✓ Market: {details['data']['title']}")
            print(f"  Volume: ${details['data']['volume']}")

            # Step 4: Place an order
            print('\n=== Step 4: Place Order ===')
            order = client.submit_order({
                'marketId': market_id,
                'outcomeId': details['data']['outcomes'][0]['outcomeId'],
                'optionId': details['data']['outcomes'][0]['options'][0]['optionId'],
                'direction': 'BUY',
                'orderType': 'PARIMUTUEL',
                'amount': 10
            })
            print(f"✓ Order placed: {order['data']['fgRequestId']}")

            # Step 5: Check positions
            print('\n=== Step 5: Check Positions ===')
            positions = client.get_user_positions(
                market_id=market_id,
                page=1,
                page_size=10
            )
            print(f"✓ You have {len(positions['data'])} position(s) in this market")

        print('\n✓ All operations completed successfully!')

    except Exception as e:
        print(f'Error: {e}')
        exit(1)

if __name__ == '__main__':
    main()
```

{% endtab %}
{% endtabs %}

## Testing Your Integration

### Prerequisites

{% tabs %}
{% tab title="Node.js" %}

```bash
# Install dependencies
npm install node-fetch

# Set environment variables
export FOREPAAS_API_KEY="your-api-key"
export FOREPAAS_PRIVATE_KEY="$(cat private_key.pem)"

# Run the example
node complete-example.js
```

{% endtab %}

{% tab title="Python" %}

```bash
# Install dependencies
pip install requests cryptography

# Set environment variables
export FOREPAAS_API_KEY="your-api-key"
export FOREPAAS_PRIVATE_KEY="$(cat private_key.pem)"

# Run the example
python complete_example.py
```

{% endtab %}
{% endtabs %}

## Best Practices

### 1. Store Credentials Securely

Never hardcode API keys or private keys in your source code. Use environment variables or a secrets management service.

### 2. Implement Connection Pooling

Reuse HTTP connections for better performance:

```javascript
// Node.js with connection pooling
const https = require('https');
const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 50
});

fetch(url, { agent });
```

### 3. Cache Market Data

Market data doesn't change every second. Cache it to reduce API calls:

```javascript
const cache = new Map();
const CACHE_TTL = 60000; // 1 minute

async function getMarketWithCache(marketId) {
  const cached = cache.get(marketId);
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }
  
  const data = await client.getMarketDetails(marketId);
  cache.set(marketId, { data, timestamp: Date.now() });
  return data;
}
```

### 4. Handle Rate Limits Gracefully

Implement exponential backoff (see [Error Handling](/getting-started/error-handling.md) for examples).

### 5. Log All Transactions

Keep a record of all orders and transactions for auditing and debugging:

```javascript
function logTransaction(type, data) {
  console.log(JSON.stringify({
    timestamp: new Date().toISOString(),
    type,
    data
  }));
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forepaas.org/advanced/code-examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
