# Partner Integration Guide

**BondBricks Partner API v1.0 - Complete Integration Guide**

---

## Table of Contents

1. [Integration Overview](#integration-overview)
2. [Authentication & Security](#authentication--security)
3. [API Endpoints Reference](#api-endpoints-reference)
4. [Code Examples](#code-examples)
5. [Webhook Integration](#webhook-integration)
6. [Error Handling & Retry Logic](#error-handling--retry-logic)
7. [Performance Optimization](#performance-optimization)
8. [Production Deployment](#production-deployment)
9. [Monitoring & Observability](#monitoring--observability)
10. [Troubleshooting](#troubleshooting)

---

## Integration Overview

### Architecture

```
┌─────────────────┐         ┌──────────────────┐         ┌─────────────────┐
│   Your System   │ ◄─────► │  BondBricks API  │ ◄─────► │   Database      │
│  (Bond Issuer)  │  HTTPS  │   (REST API)     │         │   (PostgreSQL)  │
└─────────────────┘         └──────────────────┘         └─────────────────┘
        │                            │
        │                            │
        ▼                            ▼
  ┌──────────┐              ┌──────────────┐
  │ Webhooks │              │  Rate Limiter│
  │ Endpoint │              │  (Redis)     │
  └──────────┘              └──────────────┘
```

### Integration Methods

1. **Polling** (Simple, recommended for < 100 investments/day)
   - Poll `/investments` endpoint every 15-30 minutes
   - Filter by `partner_status=PENDING`
   - Confirm via single or bulk endpoint

2. **Webhooks** (Real-time, recommended for > 100 investments/day)
   - Receive `investment.created` events
   - Process asynchronously
   - Confirm via API endpoint

3. **Hybrid** (Optimal for reliability)
   - Use webhooks for real-time processing
   - Poll every hour as backup for missed events

### Integration Timeline

| Phase | Duration | Activities |
|-------|----------|-----------|
| **Phase 1: Setup** | Week 1 | API key, sandbox testing, webhook config |
| **Phase 2: Development** | Weeks 2-3 | Build integration, error handling, logging |
| **Phase 3: Testing** | Week 4 | Load testing, edge cases, security review |
| **Phase 4: Go-Live** | Week 5 | Production deployment, monitoring |

---

## Authentication & Security

### API Key Management

**Generate API Key**:
Contact partners@bondbricks.com with:
- Institution name and regulatory license number
- Technical contact (name, email, phone)
- IP whitelist (optional, recommended for production)

**Store Securely**:
```bash
# Environment variable (recommended)
export BONDBRICKS_API_KEY="sk_live_abc123..."

# Never commit to Git
echo "BONDBRICKS_API_KEY=sk_live_abc123..." >> .env
echo ".env" >> .gitignore
```

**Rotate Keys**:
- Rotate keys every 90 days
- Support dual-key setup during rotation (old + new key)
- Revoke old key after transition period

### Request Signing (Optional, Enterprise Only)

For additional security, sign requests with HMAC-SHA256:

```python
import hmac
import hashlib
import time

def sign_request(api_secret, method, path, body=""):
    timestamp = str(int(time.time()))
    message = f"{method}\n{path}\n{timestamp}\n{body}"
    signature = hmac.new(
        api_secret.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()
    
    return {
        "X-Signature": signature,
        "X-Timestamp": timestamp
    }
```

### IP Whitelisting

Contact partners@bondbricks.com to enable IP whitelisting:
- Provide static IP addresses or CIDR ranges
- Requests from non-whitelisted IPs will receive 403 Forbidden
- Update whitelist before changing infrastructure

---

## API Endpoints Reference

### 1. List Investments

**GET** `/api/v1/investments`

Query pending investments awaiting confirmation.

**Query Parameters**:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `status` | string | - | Filter by status: `PENDING`, `COMPLETED`, `FAILED` |
| `partner_status` | string | - | Filter by partner status: `PENDING`, `CONFIRMED`, `REJECTED` |
| `created_after` | ISO 8601 | - | Filter investments created after date |
| `created_before` | ISO 8601 | - | Filter investments created before date |
| `property_id` | string | - | Filter by specific property |
| `page` | integer | 1 | Page number for pagination |
| `limit` | integer | 50 | Results per page (max: 100) |
| `offset` | integer | 0 | Skip N results (alternative to page) |

**Example**:
```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://www.bondbricks.com/api/v1/investments?partner_status=PENDING&limit=100"
```

**Response** (200 OK):
```json
{
  "data": [
    {
      "id": "inv_abc123",
      "investorId": "usr_def456",
      "investorEmail": "investor@example.com",
      "propertyId": "prop_ghi789",
      "propertyName": "Sydney CBD Commercial Tower",
      "amount": 50000,
      "units": 50,
      "unitPrice": 1000,
      "status": "COMPLETED",
      "partnerStatus": "PENDING",
      "createdAt": "2026-04-01T10:30:00Z",
      "metadata": {
        "kycStatus": "APPROVED",
        "accreditedInvestor": true
      }
    }
  ],
  "pagination": {
    "total": 150,
    "page": 1,
    "limit": 100,
    "hasMore": true
  }
}
```

### 2. Get Investment Details

**GET** `/api/v1/investments/{id}`

Retrieve full details for a specific investment.

**Example**:
```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://www.bondbricks.com/api/v1/investments/inv_abc123"
```

**Response** (200 OK):
```json
{
  "id": "inv_abc123",
  "investorId": "usr_def456",
  "investor": {
    "id": "usr_def456",
    "email": "investor@example.com",
    "name": "John Doe",
    "kycStatus": "APPROVED",
    "accreditedInvestor": true
  },
  "property": {
    "id": "prop_ghi789",
    "name": "Sydney CBD Commercial Tower",
    "address": "123 George St, Sydney NSW 2000",
    "type": "COMMERCIAL",
    "expectedReturn": 8.5,
    "maturityDate": "2028-04-01"
  },
  "amount": 50000,
  "units": 50,
  "unitPrice": 1000,
  "fees": 875,
  "netAmount": 49125,
  "status": "COMPLETED",
  "partnerStatus": "PENDING",
  "paymentMethod": "BANK_TRANSFER",
  "createdAt": "2026-04-01T10:30:00Z",
  "confirmedAt": null
}
```

### 3. Confirm Single Investment

**POST** `/api/v1/confirmations`

Confirm or reject a single investment.

**Request Body**:
```json
{
  "investmentId": "inv_abc123",
  "partnerBondRef": "BOND-2026-001",
  "status": "CONFIRMED",
  "confirmationDate": "2026-04-02",
  "notes": "Bond allocated successfully",
  "metadata": {
    "bondIsin": "AU0000XVGZA3",
    "couponRate": 8.5,
    "issueDate": "2026-04-02"
  }
}
```

**Field Validations**:
- `investmentId`: Must exist and have `partnerStatus = PENDING`
- `partnerBondRef`: Required, max 100 characters, alphanumeric + dashes
- `status`: Either `CONFIRMED` or `REJECTED`
- `confirmationDate`: YYYY-MM-DD format, cannot be future date
- `notes`: Optional, max 500 characters
- `metadata`: Optional JSON object, max 5KB

**Response** (201 Created):
```json
{
  "id": "conf_xyz789",
  "investmentId": "inv_abc123",
  "partnerBondRef": "BOND-2026-001",
  "status": "CONFIRMED",
  "confirmationDate": "2026-04-02",
  "confirmedAt": "2026-04-02T14:25:00Z",
  "notes": "Bond allocated successfully"
}
```

### 4. Bulk Confirm (JSON)

**POST** `/api/v1/confirmations/bulk`

Confirm multiple investments in a single request.

**Request Body**:
```json
{
  "confirmations": [
    {
      "investmentId": "inv_abc123",
      "partnerBondRef": "BOND-2026-001",
      "status": "CONFIRMED",
      "confirmationDate": "2026-04-02"
    },
    {
      "investmentId": "inv_def456",
      "partnerBondRef": "BOND-2026-002",
      "status": "CONFIRMED",
      "confirmationDate": "2026-04-02"
    }
  ]
}
```

**Limits**:
- Maximum 100 confirmations per request
- For > 100, use CSV upload or make multiple requests

**Response** (200 OK):
```json
{
  "total": 2,
  "successful": 2,
  "failed": 0,
  "results": [
    {
      "investmentId": "inv_abc123",
      "status": "success",
      "confirmationId": "conf_xyz789"
    },
    {
      "investmentId": "inv_def456",
      "status": "success",
      "confirmationId": "conf_xyz790"
    }
  ],
  "errors": []
}
```

**Partial Success** (200 OK):
```json
{
  "total": 2,
  "successful": 1,
  "failed": 1,
  "results": [
    {
      "investmentId": "inv_abc123",
      "status": "success",
      "confirmationId": "conf_xyz789"
    },
    {
      "investmentId": "inv_def456",
      "status": "error",
      "error": "Investment already confirmed"
    }
  ],
  "errors": [
    {
      "investmentId": "inv_def456",
      "message": "Investment already confirmed",
      "code": "ALREADY_CONFIRMED"
    }
  ]
}
```

### 5. Bulk Confirm (CSV Upload)

**POST** `/api/v1/uploads/confirmations`

Upload CSV file for bulk confirmations.

**Request** (multipart/form-data):
```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@confirmations.csv" \
  "https://www.bondbricks.com/api/v1/uploads/confirmations"
```

**CSV Format**:
```csv
investment_id,partner_bond_ref,status,confirmation_date,notes
inv_abc123,BOND-2026-001,CONFIRMED,2026-04-02,Bond allocated
inv_def456,BOND-2026-002,CONFIRMED,2026-04-02,Bond allocated
inv_ghi789,,REJECTED,2026-04-02,Insufficient collateral
```

**CSV Requirements**:
- Header row required
- UTF-8 encoding
- Maximum 10MB file size
- Maximum 10,000 rows
- Columns: `investment_id` (required), `partner_bond_ref` (required for CONFIRMED), `status` (required), `confirmation_date` (required), `notes` (optional)

**Response** (202 Accepted):
```json
{
  "uploadId": "upload_abc123",
  "status": "processing",
  "totalRows": 1000,
  "message": "CSV uploaded successfully. Processing will complete within 5 minutes.",
  "webhookUrl": "https://your-webhook.com/confirmations"
}
```

**Processing Complete Webhook**:
```json
{
  "event": "upload.completed",
  "data": {
    "uploadId": "upload_abc123",
    "totalRows": 1000,
    "successful": 985,
    "failed": 15,
    "resultsUrl": "https://www.bondbricks.com/api/v1/uploads/upload_abc123/results"
  }
}
```

---

## Code Examples

### Python

```python
import requests
from typing import List, Dict

class BondBricksClient:
    def __init__(self, api_key: str, base_url: str = "https://www.bondbricks.com/api/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        })
    
    def get_pending_investments(self, limit: int = 100) -> List[Dict]:
        """Fetch pending investments awaiting confirmation."""
        response = self.session.get(
            f"{self.base_url}/investments",
            params={
                "status": "COMPLETED",
                "partner_status": "PENDING",
                "limit": limit
            }
        )
        response.raise_for_status()
        return response.json()["data"]
    
    def confirm_investment(self, investment_id: str, bond_ref: str, 
                          confirmation_date: str, notes: str = "") -> Dict:
        """Confirm a single investment."""
        response = self.session.post(
            f"{self.base_url}/confirmations",
            json={
                "investmentId": investment_id,
                "partnerBondRef": bond_ref,
                "status": "CONFIRMED",
                "confirmationDate": confirmation_date,
                "notes": notes
            }
        )
        response.raise_for_status()
        return response.json()
    
    def bulk_confirm(self, confirmations: List[Dict]) -> Dict:
        """Confirm multiple investments in bulk."""
        response = self.session.post(
            f"{self.base_url}/confirmations/bulk",
            json={"confirmations": confirmations}
        )
        response.raise_for_status()
        return response.json()

# Usage
client = BondBricksClient(api_key="sk_live_abc123...")
pending = client.get_pending_investments()

for inv in pending:
    result = client.confirm_investment(
        investment_id=inv["id"],
        bond_ref=f"BOND-{inv['id'][-6:]}",
        confirmation_date="2026-04-02",
        notes="Automated confirmation"
    )
    print(f"Confirmed {inv['id']}: {result['id']}")
```

### Node.js/TypeScript

```typescript
import axios, { AxiosInstance } from 'axios';

interface Investment {
  id: string;
  amount: number;
  partnerStatus: string;
}

interface Confirmation {
  investmentId: string;
  partnerBondRef: string;
  status: 'CONFIRMED' | 'REJECTED';
  confirmationDate: string;
  notes?: string;
}

class BondBricksClient {
  private client: AxiosInstance;

  constructor(apiKey: string, baseURL: string = 'https://www.bondbricks.com/api/v1') {
    this.client = axios.create({
      baseURL,
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json'
      }
    });
  }

  async getPendingInvestments(limit: number = 100): Promise<Investment[]> {
    const response = await this.client.get('/investments', {
      params: {
        status: 'COMPLETED',
        partner_status: 'PENDING',
        limit
      }
    });
    return response.data.data;
  }

  async confirmInvestment(confirmation: Confirmation) {
    const response = await this.client.post('/confirmations', confirmation);
    return response.data;
  }

  async bulkConfirm(confirmations: Confirmation[]) {
    const response = await this.client.post('/confirmations/bulk', {
      confirmations
    });
    return response.data;
  }
}

// Usage
const client = new BondBricksClient('sk_live_abc123...');

(async () => {
  const pending = await client.getPendingInvestments();
  
  for (const inv of pending) {
    const result = await client.confirmInvestment({
      investmentId: inv.id,
      partnerBondRef: `BOND-${inv.id.slice(-6)}`,
      status: 'CONFIRMED',
      confirmationDate: '2026-04-02',
      notes: 'Automated confirmation'
    });
    console.log(`Confirmed ${inv.id}: ${result.id}`);
  }
})();
```

### Ruby

```ruby
require 'net/http'
require 'json'
require 'uri'

class BondBricksClient
  def initialize(api_key, base_url = 'https://www.bondbricks.com/api/v1')
    @api_key = api_key
    @base_url = base_url
  end

  def get_pending_investments(limit = 100)
    uri = URI("#{@base_url}/investments")
    uri.query = URI.encode_www_form({
      status: 'COMPLETED',
      partner_status: 'PENDING',
      limit: limit
    })
    
    response = make_request(uri, :get)
    JSON.parse(response.body)['data']
  end

  def confirm_investment(investment_id, bond_ref, confirmation_date, notes = '')
    uri = URI("#{@base_url}/confirmations")
    body = {
      investmentId: investment_id,
      partnerBondRef: bond_ref,
      status: 'CONFIRMED',
      confirmationDate: confirmation_date,
      notes: notes
    }
    
    response = make_request(uri, :post, body)
    JSON.parse(response.body)
  end

  private

  def make_request(uri, method, body = nil)
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    request = case method
              when :get then Net::HTTP::Get.new(uri)
              when :post then Net::HTTP::Post.new(uri)
              end

    request['Authorization'] = "Bearer #{@api_key}"
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    http.request(request)
  end
end

# Usage
client = BondBricksClient.new('sk_live_abc123...')
pending = client.get_pending_investments

pending.each do |inv|
  result = client.confirm_investment(
    inv['id'],
    "BOND-#{inv['id'][-6..-1]}",
    '2026-04-02',
    'Automated confirmation'
  )
  puts "Confirmed #{inv['id']}: #{result['id']}"
end
```

### PHP

```php
<?php

class BondBricksClient {
    private $apiKey;
    private $baseUrl;

    public function __construct($apiKey, $baseUrl = 'https://www.bondbricks.com/api/v1') {
        $this->apiKey = $apiKey;
        $this->baseUrl = $baseUrl;
    }

    public function getPendingInvestments($limit = 100) {
        $url = $this->baseUrl . '/investments?' . http_build_query([
            'status' => 'COMPLETED',
            'partner_status' => 'PENDING',
            'limit' => $limit
        ]);

        $response = $this->makeRequest($url, 'GET');
        return json_decode($response, true)['data'];
    }

    public function confirmInvestment($investmentId, $bondRef, $confirmationDate, $notes = '') {
        $url = $this->baseUrl . '/confirmations';
        $data = [
            'investmentId' => $investmentId,
            'partnerBondRef' => $bondRef,
            'status' => 'CONFIRMED',
            'confirmationDate' => $confirmationDate,
            'notes' => $notes
        ];

        $response = $this->makeRequest($url, 'POST', $data);
        return json_decode($response, true);
    }

    private function makeRequest($url, $method, $data = null) {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $this->apiKey,
            'Content-Type: application/json'
        ]);

        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode >= 400) {
            throw new Exception("API request failed with status $httpCode: $response");
        }

        return $response;
    }
}

// Usage
$client = new BondBricksClient('sk_live_abc123...');
$pending = $client->getPendingInvestments();

foreach ($pending as $inv) {
    $result = $client->confirmInvestment(
        $inv['id'],
        'BOND-' . substr($inv['id'], -6),
        '2026-04-02',
        'Automated confirmation'
    );
    echo "Confirmed {$inv['id']}: {$result['id']}\n";
}
```

---

## Webhook Integration

### Setup

1. **Provide webhook URL** to partners@bondbricks.com
2. **Secure your endpoint** with HTTPS and authentication
3. **Implement idempotency** to handle duplicate events
4. **Return 2xx status** within 10 seconds

### Webhook Events

#### `investment.created`

Sent when a new investment is completed and ready for confirmation.

**Payload**:
```json
{
  "event": "investment.created",
  "id": "evt_abc123",
  "data": {
    "id": "inv_abc123",
    "investorId": "usr_def456",
    "propertyId": "prop_ghi789",
    "amount": 50000,
    "units": 50,
    "status": "COMPLETED",
    "partnerStatus": "PENDING",
    "createdAt": "2026-04-01T10:30:00Z"
  },
  "timestamp": "2026-04-01T10:30:01Z"
}
```

#### `investment.confirmed`

Sent when you confirm an investment via API.

**Payload**:
```json
{
  "event": "investment.confirmed",
  "id": "evt_def456",
  "data": {
    "id": "inv_abc123",
    "partnerBondRef": "BOND-2026-001",
    "confirmationDate": "2026-04-02",
    "confirmedAt": "2026-04-02T14:25:00Z"
  },
  "timestamp": "2026-04-02T14:25:01Z"
}
```

### Webhook Signature Verification

All webhooks include an `X-Webhook-Signature` header for verification:

```python
import hmac
import hashlib

def verify_webhook(payload: str, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

# Usage in Flask
@app.route('/webhooks/bondbricks', methods=['POST'])
def handle_webhook():
    payload = request.data.decode('utf-8')
    signature = request.headers.get('X-Webhook-Signature')
    
    if not verify_webhook(payload, signature, WEBHOOK_SECRET):
        return 'Invalid signature', 401
    
    event = request.json
    # Process event...
    return '', 200
```

### Retry Policy

- **Failed webhook** (non-2xx response or timeout): 3 retries
- **Backoff**: Exponential (1 min, 5 min, 15 min)
- **Timeout**: 10 seconds per attempt
- **Final failure**: Email notification to technical contact

---

## Error Handling & Retry Logic

### Exponential Backoff

```python
import time
import requests

def api_call_with_retry(func, max_retries=3):
    for attempt in range(max_retries):
        try:
            return func()
        except requests.HTTPError as e:
            if e.response.status_code == 429:  # Rate limit
                retry_after = int(e.response.headers.get('Retry-After', 60))
                time.sleep(retry_after)
            elif e.response.status_code >= 500:  # Server error
                backoff = 2 ** attempt  # 1s, 2s, 4s
                time.sleep(backoff)
            else:
                raise  # Don't retry client errors (4xx)
    raise Exception(f"Failed after {max_retries} retries")
```

### Idempotency

Use `X-Idempotency-Key` header for safe retries:

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Idempotency-Key: confirm-inv_abc123-20260402" \
  -d '{"investmentId": "inv_abc123", ...}' \
  "https://www.bondbricks.com/api/v1/confirmations"
```

Same `X-Idempotency-Key` = Same response (no duplicate confirmations)

---

## Performance Optimization

### Pagination Best Practices

```python
def fetch_all_pending_investments():
    all_investments = []
    page = 1
    
    while True:
        response = client.get('/investments', params={
            'partner_status': 'PENDING',
            'page': page,
            'limit': 100  # Maximum allowed
        })
        
        data = response.json()
        all_investments.extend(data['data'])
        
        if not data['pagination']['hasMore']:
            break
        
        page += 1
    
    return all_investments
```

### Batch Processing

Process confirmations in batches of 100:

```python
def batch_confirm(investments, batch_size=100):
    for i in range(0, len(investments), batch_size):
        batch = investments[i:i+batch_size]
        confirmations = [
            {
                "investmentId": inv['id'],
                "partnerBondRef": generate_bond_ref(inv),
                "status": "CONFIRMED",
                "confirmationDate": today()
            }
            for inv in batch
        ]
        
        result = client.bulk_confirm(confirmations)
        log_results(result)
```

### Connection Pooling

Reuse HTTP connections for better performance:

```python
import requests

session = requests.Session()
adapter = requests.adapters.HTTPAdapter(
    pool_connections=10,
    pool_maxsize=20,
    max_retries=3
)
session.mount('https://', adapter)
```

---

## Production Deployment

### Pre-Launch Checklist

- [ ] API key stored securely (environment variable, secrets manager)
- [ ] IP whitelist configured (if using)
- [ ] Webhook endpoint secured with HTTPS
- [ ] Webhook signature verification implemented
- [ ] Error handling and retry logic in place
- [ ] Logging configured (API requests, responses, errors)
- [ ] Monitoring alerts configured
- [ ] Load testing completed (1000+ requests)
- [ ] Security review completed
- [ ] Runbook created for on-call team

### Environment Configuration

```bash
# Production
BONDBRICKS_API_KEY=sk_live_...
BONDBRICKS_BASE_URL=https://www.bondbricks.com/api/v1
BONDBRICKS_WEBHOOK_SECRET=whsec_...

# Staging
BONDBRICKS_API_KEY=sk_test_...
BONDBRICKS_BASE_URL=https://sandbox.bondbricks.com/api/v1
BONDBRICKS_WEBHOOK_SECRET=whsec_test_...
```

### Rate Limit Management

Monitor `X-RateLimit-*` headers:

```python
response = client.get('/investments')

remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
reset_time = int(response.headers.get('X-RateLimit-Reset', 0))

if remaining < 10:
    sleep_seconds = reset_time - time.time()
    time.sleep(max(0, sleep_seconds))
```

---

## Monitoring & Observability

### Metrics to Track

1. **Request Metrics**:
   - Requests per minute
   - Success rate (2xx/total)
   - Error rate by status code
   - Latency (p50, p95, p99)

2. **Business Metrics**:
   - Pending investments count
   - Confirmations per hour
   - Average time to confirmation
   - Rejection rate

3. **System Health**:
   - API availability
   - Webhook delivery success rate
   - Connection pool utilization

### Logging Best Practices

```python
import logging
import json

logger = logging.getLogger(__name__)

def log_api_call(method, url, status_code, duration_ms, request_id):
    logger.info(json.dumps({
        "event": "api_call",
        "method": method,
        "url": url,
        "status_code": status_code,
        "duration_ms": duration_ms,
        "request_id": request_id,
        "timestamp": datetime.utcnow().isoformat()
    }))
```

### Alerts

Configure alerts for:
- Error rate > 5%
- Latency p99 > 5 seconds
- Pending investments > 1000
- Webhook failure rate > 10%

---

## Troubleshooting

### Common Issues

#### 401 Unauthorized
**Cause**: Invalid or missing API key
**Fix**: Verify API key is correct and not expired

#### 429 Rate Limit Exceeded
**Cause**: Too many requests
**Fix**: Implement exponential backoff, reduce request frequency

#### 422 Validation Error
**Cause**: Invalid request data
**Fix**: Check error response details, validate data format

#### 500 Server Error
**Cause**: BondBricks server issue
**Fix**: Retry with exponential backoff, contact support if persistent

### Debug Mode

Enable verbose logging:

```python
import logging
import http.client

http.client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
```

---

## Support & Resources

**Technical Support**: api-support@bondbricks.com
**Partner Team**: partners@bondbricks.com
**Documentation**: https://www.bondbricks.com/api-docs
**Status Page**: https://status.bondbricks.com

**SLA**:
- Standard: 4 business hours
- Enterprise: 1 hour (24/7)

---

**Last Updated**: April 2026
**API Version**: 1.0
**Guide Version**: 1.0
