# Common Pitfalls

This page lists the most common integration mistakes developers make when working with the ForePaaS API, along with solutions.

## Authentication & Signing Errors

### 1. **Invalid Signature (401)**

**Problem:** Most common error - signature validation fails

**Common Causes:**

* ❌ Including domain in the signed path (`https://apidev.forepass.org/api/user/...`)
* ❌ Not including query parameters in the signed path
* ❌ Whitespace differences in JSON body
* ❌ Wrong key order in JSON body
* ❌ Timestamp is more than 5 minutes off
* ❌ Reusing nonces across requests
* ❌ Wrong Content-Type in signature

**Solutions:**

```javascript
// ✅ CORRECT
const path = '/api/user/openapi/authorize';  // No domain
const signContent = `POST\napplication/json\n${path}\n${jsonBody}\n${timestamp}\n${nonce}`;

// ❌ WRONG
const path = 'https://apidev.forepass.org/api/user/openapi/authorize';
```

For endpoints with query parameters:

```javascript
// ✅ CORRECT - Include query params in signed path
const path = '/api/market/openapi/market/list?page=1&pageSize=10';

// ❌ WRONG - Missing query params
const path = '/api/market/openapi/market/list';
```

### 2. **Field Name Typo: marchantUserId**

**Problem:** Field is spelled `marchantUserId` (not `merchantUserId`)

**Solution:**

```json
// ✅ CORRECT
{
  "marchantUserId": "user123"
}

// ❌ WRONG
{
  "merchantUserId": "user123"
}
```

This is **not a typo** in the documentation - use the exact spelling shown.

### 3. **Missing Required Headers**

**Problem:** Forgetting headers for API Key authentication

**Solution:** All `/authorize` requests need 5 headers:

```bash
-H "Content-Type: application/json"
-H "X-API-KEY: your-key"
-H "X-Signature: base64-signature"
-H "X-Timestamp: 1704067200000"
-H "X-Nonce: unique-random-string"
```

JWT endpoints only need:

```bash
-H "Authorization: Bearer your-jwt-token"
```

### 4. **Clock Skew Issues**

**Problem:** Signature timestamps rejected

**Causes:**

* System clock is wrong
* Using cached timestamp
* Timezone confusion

**Solutions:**

* Use `Date.now()` or `time.time() * 1000` to get current Unix milliseconds
* Generate timestamp fresh for each request
* Ensure your server's clock is synchronized (use NTP)
* Timestamp must be within **±5 minutes** of server time

## Request Structure Errors

### 5. **Wrong Parameter Placement**

**Problem:** Putting parameters in wrong location (body vs query vs path)

**Common Mistakes:**

| Endpoint               | Wrong ❌            | Correct ✅                           |
| ---------------------- | ------------------ | ----------------------------------- |
| Market Top Holders     | `marketId` in body | `marketId` as query param           |
| User Notification List | No `userId`        | `userId` in query params (required) |
| User Positions         | No `marketId`      | `marketId` in body (optional)       |

### 6. **BUY vs SELL Field Confusion**

**Problem:** Using wrong fields for order direction

**Solution:**

**For BUY orders:**

```json
{
  "direction": "BUY",
  "amount": 100,     // ✅ Amount to spend
  "shares": null     // ❌ Don't include shares
}
```

**For SELL orders:**

```json
{
  "direction": "SELL",
  "shares": 50,      // ✅ Shares to sell
  "amount": null     // ❌ Don't include amount
}
```

### 7. **Duplicate Keys in Market Application**

**Problem:** JSON with duplicate keys (invalid JSON)

**Wrong ❌:**

```json
{
  "marketType": "PARIMUTUEL",
  "marketType": "PREDICTION"  // Duplicate key!
}
```

**Correct ✅:**

```json
{
  "modelType": "PARIMUTUEL",
  "marketType": "PARIMUTUEL"
}
```

### 8. **Weight Validation Failure**

**Problem:** Option weights don't sum to 1.0

**Wrong ❌:**

```json
"outcomeOptionsVoList": [
  { "optionTitle": "YES", "weight": 1 },
  { "optionTitle": "NO", "weight": 1 }   // Sum = 2.0
]
```

**Correct ✅:**

```json
"outcomeOptionsVoList": [
  { "optionTitle": "YES", "weight": 0.5 },
  { "optionTitle": "NO", "weight": 0.5 }   // Sum = 1.0
]
```

## Async Pattern Mistakes

### 9. **Assuming Immediate Order Execution**

**Problem:** Treating order submit as synchronous

**Wrong ❌:**

```javascript
const order = await submitOrder(data);
console.log(`Order status: ${order.data.status}`);  // ❌ status doesn't exist
```

**Correct ✅:**

```javascript
const order = await submitOrder(data);
const fgRequestId = order.data.fgRequestId;

// Poll for result
const result = await getTransactionResult(fgRequestId);
if (result.data.status === 'SUCCESS') {
  console.log('Order completed successfully');
}
```

### 10. **Retrying Orders Without Checking Status**

**Problem:** Retrying failed requests creates duplicate orders

**Wrong ❌:**

```javascript
try {
  await submitOrder(data);
} catch (error) {
  await submitOrder(data);  // ❌ May create duplicate!
}
```

**Correct ✅:**

```javascript
const order = await submitOrder(data);
const fgRequestId = order.data.fgRequestId;

// Always check result before retry
const result = await getTransactionResult(fgRequestId);
if (result.data.status === 'FAILED') {
  // Only retry if genuinely failed
  await submitOrder(data);
}
```

## Response Handling Errors

### 11. **Accessing Non-Existent Response Fields**

**Problem:** Challenge response returns `data: null` but code tries to access fields

**Wrong ❌:**

```javascript
const result = await challengeMarket(data);
console.log(`Challenge ID: ${result.data.challengeId}`);  // ❌ Crash! data is null
```

**Correct ✅:**

```javascript
const result = await challengeMarket(data);
if (result.code === 200) {
  console.log('Challenge submitted successfully');
}
```

### 12. **Ignoring Pagination**

**Problem:** Only reading first page of results

**Wrong ❌:**

```javascript
const positions = await getUserPositions(1, 10);
// Only shows 10 positions, might have 100+
```

**Correct ✅:**

```javascript
let allPositions = [];
let page = 1;
let hasMore = true;

while (hasMore) {
  const result = await getUserPositions(page, 10);
  allPositions.push(...result.data);
  hasMore = page < result.pages;
  page++;
}
```

## Rate Limiting Mistakes

### 13. **No Backoff Strategy**

**Problem:** Hammering API after 429 responses

**Wrong ❌:**

```javascript
while (true) {
  try {
    await makeRequest();
    break;
  } catch (err) {
    // Immediately retry
  }
}
```

**Correct ✅:**

```javascript
async function retryWithBackoff(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.code === 429 || error.code >= 500) {
        const delay = Math.pow(2, i) * 1000;  // 1s, 2s, 4s
        await sleep(delay);
      } else {
        throw error;
      }
    }
  }
}
```

## Security Mistakes

### 14. **Exposing Private Keys**

**Problem:** Committing secrets to git or client-side code

**Wrong ❌:**

```javascript
const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIE...";  // In source code
```

**Correct ✅:**

```javascript
const privateKey = process.env.FOREPAAS_PRIVATE_KEY;  // From env vars
```

### 15. **Logging Sensitive Data**

**Problem:** Logging tokens, signatures, or keys

**Wrong ❌:**

```javascript
console.log('Token:', token);  // Token in logs
console.log('Signature:', signature);
```

**Correct ✅:**

```javascript
console.log('Token:', token.substring(0, 10) + '...');  // Masked
```

## Integration Testing Mistakes

### 16. **Using Production in Development**

**Problem:** Testing against production API

**Solution:**

* Always use **Sandbox** environment for development: `https://apidev.forepass.org`
* Only use production after thorough sandbox testing
* Never test with real user funds

### 17. **Not Checking Error Codes**

**Problem:** Assuming requests always succeed

**Wrong ❌:**

```javascript
const result = await apiCall();
const data = result.data.token;  // ❌ Might crash if error
```

**Correct ✅:**

```javascript
const result = await apiCall();
if (result.code !== 200) {
  console.error('Error:', result.msg);
  return;
}
const data = result.data.token;
```

## Quick Reference: Most Common Errors

| Error Code                            | Common Cause           | Quick Fix                                 |
| ------------------------------------- | ---------------------- | ----------------------------------------- |
| **401** `Invalid signature`           | Signature mismatch     | Check path, body, timestamp, nonce format |
| **401** `invalid token`               | Expired JWT            | Re-authenticate user                      |
| **400** `Invalid request parameters`  | Missing required field | Check parameter tables in docs            |
| **422** `Insufficient balance`        | Not enough funds       | Check user balance first                  |
| **422** `Market closed`               | Trading ended          | Check market status before orders         |
| **429** `Rate limit exceeded`         | Too many requests      | Implement exponential backoff             |
| **4039** `Weights must add up to 1`   | Invalid option weights | Sum all weights = 1.0                     |
| **5005** / **5006** `Precision error` | Too many decimals      | Round to max 8 decimal places             |

## Need Help?

If you encounter an issue not listed here:

1. Check the [Error Handling](/getting-started/error-handling.md) guide
2. Review the [Authentication](/getting-started/authentication.md) guide
3. Verify against [Code Examples](/advanced/code-examples.md)
4. Contact [Support](/resources/support.md)


---

# 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/getting-started/common-pitfalls.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.
