# Puffin Offset API Documentation

## Table of Contents
- [QR Code Generation API](#qr-code-generation-api)
  - [Endpoint](#endpoint)
  - [Request Format](#request-format)
  - [Calculation Types](#calculation-types)
  - [Response Format](#response-format)
  - [Format Comparison (PNG vs SVG)](#format-comparison-png-vs-svg)
  - [Usage Examples](#usage-examples)
- [Checkout API](#checkout-api)
- [Best Practices](#best-practices)
- [Error Handling](#error-handling)

## QR Code Generation API

### Endpoint
```
POST /api/qr-code/generate
```

Generate QR codes that encode carbon calculation parameters. The QR code directs users to the Puffin Offset calculator with pre-filled calculation data.

### Request Format

The API accepts three types of calculations:

#### 1. Fuel-Based Calculation
Calculate carbon offset based on fuel consumption:

```json
{
  "calculationType": "fuel",
  "fuelAmount": 1000,
  "fuelUnit": "liters",
  "vessel": {
    "imo": "1234567",
    "name": "Sample Yacht",
    "type": "Motor Yacht",
    "enginePower": 2250
  },
  "timestamp": "2025-03-15T10:00:00Z",
  "source": "marina-api"
}
```

**Fields:**
- `calculationType`: Must be `"fuel"`
- `fuelAmount`: Number of fuel units consumed
- `fuelUnit`: Either `"liters"` or `"gallons"`
- `vessel`: Optional vessel metadata (for informational purposes only)
- `timestamp`: Optional ISO timestamp
- `source`: Optional identifier (e.g., "marina-api", "broker-portal")

#### 2. Distance-Based Calculation
Calculate carbon offset based on trip distance and vessel characteristics:

```json
{
  "calculationType": "distance",
  "distance": 150,
  "speed": 12,
  "fuelRate": 85,
  "vessel": {
    "imo": "1234567",
    "name": "Sample Yacht",
    "type": "Motor Yacht",
    "enginePower": 2250
  },
  "timestamp": "2025-03-15T10:00:00Z",
  "source": "marina-api"
}
```

**Fields:**
- `calculationType`: Must be `"distance"`
- `distance`: Distance in nautical miles
- `speed`: Average speed in knots
- `fuelRate`: Fuel consumption rate in liters per hour
- `vessel`: Optional vessel metadata
- `timestamp`: Optional ISO timestamp
- `source`: Optional identifier

#### 3. Custom Amount
Direct monetary amount for carbon offsetting:

```json
{
  "calculationType": "custom",
  "customAmount": 250.00,
  "vessel": {
    "name": "Corporate Event",
    "type": "Conference"
  },
  "timestamp": "2025-03-15T10:00:00Z",
  "source": "event-organizer"
}
```

**Fields:**
- `calculationType`: Must be `"custom"`
- `customAmount`: Dollar amount (USD) for direct offset purchase
- `vessel`: Optional context information
- `timestamp`: Optional ISO timestamp
- `source`: Optional identifier

### Response Format

The API returns both PNG and SVG formats of the QR code:

```json
{
  "success": true,
  "data": {
    "qrCodeDataURL": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
    "qrCodeSVG": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\">...</svg>",
    "url": "https://puffinoffset.com/calculator?qr=eyJjYWxjdWxhdGlvblR5cGUiOi...",
    "expiresAt": "2025-04-14T10:00:00.000Z"
  }
}
```

**Response Fields:**
- `qrCodeDataURL`: Base64-encoded PNG image as data URL (ready for `<img>` src)
- `qrCodeSVG`: SVG markup string (ready for direct HTML injection)
- `url`: The full URL that the QR code points to
- `expiresAt`: ISO timestamp when the QR code expires (30 days from generation)

### Format Comparison (PNG vs SVG)

| Feature | PNG (qrCodeDataURL) | SVG (qrCodeSVG) |
|---------|---------------------|-----------------|
| **Format** | Base64-encoded PNG as data URL | SVG markup string |
| **Use Case** | Email, printing, basic displays | Web, scaling, professional prints |
| **File Size** | Larger (~5-10 KB) | Smaller (~2-4 KB) |
| **Scalability** | Pixelated when enlarged | Perfect at any size |
| **Browser Support** | Universal | Universal (all modern browsers) |
| **Best For** | Quick implementation, emails | Websites, responsive design, high-DPI displays |
| **Embedding** | `<img src="{qrCodeDataURL}">` | Direct HTML injection or `<img src="data:image/svg+xml,{encoded}">` |

**When to Use PNG:**
- Email campaigns (better compatibility)
- Print materials with fixed sizes
- Quick prototyping
- When exact pixel dimensions are known

**When to Use SVG:**
- Responsive web design
- High-resolution displays (Retina, 4K)
- Professional print materials (scales to any size)
- When minimizing file size is important
- Dynamic styling with CSS

### Usage Examples

#### cURL
```bash
curl -X POST https://puffinoffset.com/api/qr-code/generate \
  -H "Content-Type: application/json" \
  -d '{
    "calculationType": "distance",
    "distance": 150,
    "speed": 12,
    "fuelRate": 85,
    "vessel": {
      "imo": "1234567",
      "name": "Sample Yacht"
    }
  }'
```

#### JavaScript (Fetch API)
```javascript
const response = await fetch('https://puffinoffset.com/api/qr-code/generate', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    calculationType: 'fuel',
    fuelAmount: 1000,
    fuelUnit: 'liters',
    vessel: {
      name: 'Sample Yacht',
      imo: '1234567'
    }
  })
});

const { data } = await response.json();
console.log('QR Code URL:', data.url);

// Use PNG format
document.getElementById('qr-png').src = data.qrCodeDataURL;

// Use SVG format
document.getElementById('qr-svg-container').innerHTML = data.qrCodeSVG;
```

#### Python
```python
import requests

response = requests.post(
    'https://puffinoffset.com/api/qr-code/generate',
    json={
        'calculationType': 'custom',
        'customAmount': 250.00,
        'source': 'python-client'
    }
)

data = response.json()['data']
print(f"QR Code URL: {data['url']}")
print(f"Expires at: {data['expiresAt']}")

# Save PNG to file
import base64
png_data = data['qrCodeDataURL'].split(',')[1]
with open('qr-code.png', 'wb') as f:
    f.write(base64.b64decode(png_data))

# Save SVG to file
with open('qr-code.svg', 'w') as f:
    f.write(data['qrCodeSVG'])
```

#### HTML Embedding

**PNG Format:**
```html
<!-- Direct data URL in img tag -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..."
     alt="Carbon Offset QR Code"
     style="width: 300px; height: 300px;">
```

**SVG Format:**
```html
<!-- Direct SVG injection (recommended for web) -->
<div id="qr-container">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
    <!-- SVG content from API -->
  </svg>
</div>

<!-- Or as data URL -->
<img src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'>...</svg>"
     alt="Carbon Offset QR Code"
     style="width: 100%; max-width: 400px;">
```

**Dynamic Sizing with SVG:**
```css
/* SVG automatically scales to container */
#qr-container {
  width: 100%;
  max-width: 500px;
  margin: 0 auto;
}

#qr-container svg {
  width: 100%;
  height: auto;
}
```

## Checkout API

### Create Checkout Session
```
POST /api/checkout/create-session
```

Create a Stripe checkout session for carbon offset purchase.

**Request Body:**
```json
{
  "tons": 2.5,
  "portfolioId": 123,
  "pricePerTon": 20.00,
  "customerEmail": "customer@example.com"
}
```

**Response:**
```json
{
  "sessionId": "cs_test_...",
  "url": "https://checkout.stripe.com/...",
  "orderId": "order_abc123"
}
```

**Note:** Vessel information is NOT included in checkout sessions or stored in orders. Vessel metadata in QR codes is for informational purposes only.

### Get Order Details
```
GET /api/checkout/session/{sessionId}
```

Retrieve order details by Stripe session ID.

**Response:**
```json
{
  "order": {
    "id": "order_abc123",
    "tons": 2.5,
    "portfolioId": 123,
    "baseAmount": 5000,
    "processingFee": 180,
    "totalAmount": 5180,
    "currency": "USD",
    "status": "paid",
    "wrenOrderId": "wren_xyz789",
    "stripeSessionId": "cs_test_...",
    "createdAt": "2025-03-15T10:00:00.000Z"
  },
  "session": {
    "paymentStatus": "paid",
    "customerEmail": "customer@example.com"
  }
}
```

## Best Practices

### QR Code Generation

1. **Choose the Right Format:**
   - Use **PNG** for emails, fixed-size prints, and quick prototypes
   - Use **SVG** for websites, responsive designs, and high-quality prints

2. **Include Metadata:**
   - Always include `source` field to track where QR codes originate
   - Include `timestamp` for auditing and expiration tracking
   - Use descriptive `vessel` names for context

3. **Handle Expiration:**
   - QR codes expire after 30 days
   - Check `expiresAt` timestamp in response
   - Regenerate QR codes if needed for long-term use

4. **Error Handling:**
   - Validate input data before sending to API
   - Handle network failures gracefully
   - Display user-friendly error messages

### Integration Recommendations

1. **Marinas & Brokers:**
   - Generate QR codes after trip logging
   - Print QR codes on receipts or invoices
   - Include vessel details for tracking

2. **Event Organizers:**
   - Use `custom` calculation type for flat-rate offsets
   - Generate bulk QR codes for attendee packets
   - Track source with `source` field

3. **Mobile Apps:**
   - Use SVG format for responsive display
   - Cache QR codes locally to reduce API calls
   - Implement QR code scanning for peer-to-peer sharing

## Error Handling

### Error Response Format
```json
{
  "success": false,
  "error": "Invalid calculation type"
}
```

### Common Errors

| Error | Cause | Solution |
|-------|-------|----------|
| "Invalid calculation type" | `calculationType` not "fuel", "distance", or "custom" | Use valid calculation type |
| "Missing required fields" | Required fields for calculation type not provided | Check calculation type requirements |
| "Invalid fuel unit" | `fuelUnit` not "liters" or "gallons" | Use valid fuel unit |
| "Invalid amount" | Negative or zero values | Provide positive values |
| 500 Server Error | Server-side issue | Retry request, contact support if persistent |

### HTTP Status Codes

- **200 OK**: QR code generated successfully
- **400 Bad Request**: Invalid request data (check error message)
- **500 Internal Server Error**: Server-side error (retry or contact support)

## Future Enhancements

The following features are planned for future releases:

1. **Authentication:** API key authentication for rate limiting and analytics
2. **Batch Generation:** Generate multiple QR codes in a single request
3. **Custom Branding:** Add logos or custom colors to QR codes
4. **Analytics Dashboard:** Track QR code scans and conversion rates
5. **Webhook Support:** Receive notifications when QR codes are scanned or orders completed

## Changelog

### Version 1.0 (Current)
- Initial release
- Support for fuel-based, distance-based, and custom amount calculations
- PNG and SVG format outputs
- 30-day expiration
- No authentication required

---

**Support:** For questions or issues, contact [support@puffinoffset.com](mailto:support@puffinoffset.com)

**API Base URL:** `https://puffinoffset.com/api`
