puffin-app/API_DOCUMENTATION.md
Matt 48022f38d4
All checks were successful
Build and Push Docker Images / docker (push) Successful in 22s
Add comprehensive API documentation for QR Code Generation API
- Document QR Code Generation API with three calculation types (fuel, distance, custom)
- Include PNG vs SVG format comparison table with use case recommendations
- Provide usage examples in cURL, JavaScript, Python, and HTML
- Document Checkout API endpoints
- Add best practices, error handling, and future enhancements section
- Clarify that vessel metadata in QR codes is informational only (not stored in orders)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:58:14 +01:00

11 KiB

Puffin Offset API Documentation

Table of Contents

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:

{
  "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:

{
  "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:

{
  "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:

{
  "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

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)

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

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:

<!-- 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:

<!-- 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:

/* 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:

{
  "tons": 2.5,
  "portfolioId": 123,
  "pricePerTon": 20.00,
  "customerEmail": "customer@example.com"
}

Response:

{
  "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:

{
  "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

{
  "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

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