# Server-Side Integration

## Target URL Verification

When users access your PayGate, Sigwei forwards paid requests to your target URL with authentication headers. You have two authentication modes to choose from.

## Payment Headers

**All proxied requests include these payment headers**, regardless of authentication mode:

* `X-Payment`: Base64-encoded payment authorization data (contains payer address, amount, nonce, signature, etc.)
* `X-Payment-Response`: Base64-encoded settlement response from blockchain (contains transaction hash, network, success status)

These headers allow your target server to:

* Verify the payment independently if desired
* Track which wallet paid for the request
* Link requests to on-chain transactions
* Implement custom payment verification logic

## HMAC Mode (Recommended)

When `headerAuthMode` is set to `"hmac"` (default), Sigwei adds an HMAC signature for secure authentication:

**Signature Computation**: `HMAC-SHA256(X-Payment + "|" + X-Payment-Response, secret)`

The signature proves the request came from Sigwei and includes valid payment data.

```javascript
// Node.js example - HMAC verification
const crypto = require('crypto');

app.get('/api/data', (req, res) => {
  const xPayment = req.headers['x-payment'];
  const xPaymentResponse = req.headers['x-payment-response'];
  const signatureHeader = req.headers['sigwei-auth-signature'];
  const secret = process.env.SIGWEI_SECRET; // From your paygate settings

  if (!xPayment || !xPaymentResponse) {
    return res.status(401).json({ error: 'Missing payment headers' });
  }

  if (!signatureHeader) {
    return res.status(401).json({ error: 'Missing authentication signature' });
  }

  // Construct message from payment headers
  const message = xPayment + '|' + xPaymentResponse;

  // Verify HMAC signature
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('base64');

  if (signatureHeader !== expectedSignature) {
    return res.status(403).json({ error: 'Invalid signature' });
  }

  // Optional: Decode and verify payment data independently
  const paymentData = JSON.parse(Buffer.from(xPayment, 'base64').toString());
  const settlementData = JSON.parse(Buffer.from(xPaymentResponse, 'base64').toString());

  console.log('Paid by:', paymentData.payload.authorization.from);
  console.log('Transaction:', settlementData.transaction);

  res.json({ data: 'Your protected data' });
});
```

## Plaintext Mode (Simple)

When `headerAuthMode` is set to `"plaintext"`, Sigwei adds a simple secret header:

```javascript
// Node.js example - Plaintext verification
app.get('/api/data', (req, res) => {
  const expectedSecret = process.env.SIGWEI_SECRET; // From your paygate settings
  if (req.headers['sigwei-secret'] !== expectedSecret) {
    return res.status(403).json({ error: 'Unauthorized' });
  }
  res.json({ data: 'Your protected data' });
});
```

## Why Authentication Matters

**Security Issue**: x-payment headers can be recreated from blockchain transaction data. Anyone could theoretically access protected PayGates by reconstructing payment headers from public blockchain transactions.

**Solution**: Enable `requireAuth: true` on PayGates. This ensures only the original payer (verified by wallet signature) can access content, even if someone else copies the payment header.

## Why Sigwei Secret is Crucial

**The Problem**: Without verification, anyone could bypass your PayGate by calling your API directly, avoiding payment entirely.

**The Solution**: Sigwei Secret ensures requests come from legitimate paying users via Sigwei's proxy:

* You set the secret when creating the PayGate or generate via API
* Every paid request includes authentication headers
* Your backend rejects requests without valid authentication
* Direct API access is blocked, payments are enforced

## Backend Implementation

### Python Example

```python
import hmac
import hashlib
import base64
import json
import os
from flask import Flask, request, jsonify

app = Flask(__name__)

def verify_hmac_request(request):
    x_payment = request.headers.get('x-payment')
    x_payment_response = request.headers.get('x-payment-response')
    signature_header = request.headers.get('sigwei-auth-signature')
    secret = os.environ.get('SIGWEI_SECRET')

    if not x_payment or not x_payment_response:
        return False, None, None

    if not signature_header:
        return False, None, None

    # Construct message from payment headers
    message = x_payment + '|' + x_payment_response

    # Verify HMAC signature
    expected_signature = base64.b64encode(
        hmac.new(secret.encode(), message.encode(), hashlib.sha256).digest()
    ).decode()

    if signature_header != expected_signature:
        return False, None, None

    # Optional: Decode payment data for additional verification
    payment_data = json.loads(base64.b64decode(x_payment))
    settlement_data = json.loads(base64.b64decode(x_payment_response))

    return True, payment_data, settlement_data

@app.route('/api/data')
def get_data():
    verified, payment_data, settlement_data = verify_hmac_request(request)

    if not verified:
        return jsonify({'error': 'Unauthorized'}), 403

    # Optional: Log payment information
    if payment_data:
        print(f"Paid by: {payment_data['payload']['authorization']['from']}")
        print(f"Transaction: {settlement_data['transaction']}")

    return jsonify({'data': 'Your protected data'})
```

## Managing Secrets

### Get or Regenerate Secret

```bash
# Get current secret for a PayGate
curl -X GET http://localhost:8080/api/v1/paygates/123 \
     -H "Authorization: Bearer YOUR_JWT_TOKEN"

# Regenerate secret (generates new random secret)
curl -X PATCH http://localhost:8080/api/v1/paygates/123/secret \
     -H "Authorization: Bearer YOUR_JWT_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"sigweiSecret": ""}'

# Set custom secret
curl -X PATCH http://localhost:8080/api/v1/paygates/123/secret \
     -H "Authorization: Bearer YOUR_JWT_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"sigweiSecret": "your-custom-secret"}'
```

## Request Timeouts & Size Limits

Sigwei enforces timeout and response size limits to prevent abuse and manage infrastructure costs.

### Timeout Configuration

**Default**: 10 minutes (600 seconds)

The proxy timeout determines how long Sigwei will wait for your target URL to respond. This generous default supports:

* AI endpoints (OpenAI, Claude, etc.)
* Long-running computations
* Large data processing

**When requests timeout:**

* Client receives 502 Bad Gateway
* Metrics are still captured for analytics
* Credits are **consumed** (payment was made, timeout is server-side)

**Best Practices:**

* Design APIs to respond within 10 minutes when possible
* Use async patterns for longer operations (webhook callbacks)
* Return processing IDs immediately, fetch results later
* Consider chunking large responses

### Response Size Limits

**Default**: 10MB (10,485,760 bytes)

Sigwei blocks responses exceeding this limit to prevent egress bandwidth abuse on hosting infrastructure.

**When size limit exceeded:**

* Request blocked with 502 Bad Gateway
* Warning logged with actual size and limit
* Metrics captured showing blocked request
* Credits are **consumed** (payment was made, size limit is protective)

**Handling Large Responses:**

For responses larger than 10MB, use **File PayGates** instead:

* Upload files to Sigwei's storage (R2)
* Users get presigned download URLs
* **No bandwidth cost** to Sigwei (direct R2 → user)
* Better user experience for large files

**Example - Wrong way (proxy large data):**

```bash
# ❌ This will hit the 10MB limit
curl -X POST https://402ify.com/api/v1/paygates \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -d '{
    "targetURL": "https://api.example.com/export/csv",
    "price": 100000,
    "resourceType": "url"
  }'
```

**Example - Right way (use file PayGate):**

```bash
# ✓ Use file PayGates for large content
curl -X POST https://402ify.com/api/v1/paygates \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -F "price=100000" \
  -F "resourceType=file" \
  -F "file=@large-dataset.csv"
```

### API Design Recommendations

**For API Providers:**

1. **Paginate large datasets** - Return data in chunks
2. **Stream processing** - Use streaming responses where possible
3. **Compression** - gzip/brotli compress responses
4. **Async patterns** - Return job IDs for long operations

**Example - Pagination:**

```json
{
  "data": [...],
  "pagination": {
    "page": 1,
    "limit": 100,
    "total": 5000,
    "nextPage": "/api/data?page=2"
  }
}
```

## Security Best Practices

* **Store secrets securely**: Use environment variables or key management systems
* **Validate every request**: Check authentication headers on all protected endpoints
* **Use HMAC mode**: More secure than plaintext for production environments
* **Rotate secrets regularly**: Update PayGate secrets periodically via API
* **Log access attempts**: Monitor for unauthorized patterns and failed authentications
* **Rate limiting**: Implement rate limiting on your target URLs to prevent abuse
* **Response size awareness**: Design APIs to stay under 10MB or use file PayGates for larger content
