# PHP Integration — RenderPix

**API Endpoint:** `POST https://renderpix.dev/v1/render`

---

## Authentication

Pass your API key in the `X-API-Key` header on every request.

```php
define('RENDERPIX_API_KEY', 'rpx_your_api_key');
define('RENDERPIX_ENDPOINT', 'https://renderpix.dev/v1/render');
```

---

## Basic Example — HTML to PNG (cURL)

```php
<?php

function renderHtml(string $html, string $outputFile = 'output.png'): void
{
    $payload = json_encode([
        'html'   => $html,
        'width'  => 1200,
        'height' => 630,
        'format' => 'png',
    ]);

    $ch = curl_init('https://renderpix.dev/v1/render');
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $payload,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_HTTPHEADER     => [
            'X-API-Key: rpx_your_api_key',
            'Content-Type: application/json',
        ],
    ]);

    $body   = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($status !== 200) {
        $error = json_decode($body, true);
        throw new RuntimeException("RenderPix error {$status}: " . ($error['message'] ?? 'unknown'));
    }

    file_put_contents($outputFile, $body);
    echo "Saved to {$outputFile}\n";
}

renderHtml('<h1 style="font-family:sans-serif;color:#1e293b">Hello, RenderPix!</h1>');
```

---

## Real-World Example — OG Image Generator

```php
<?php

function generateOgImage(
    string $title,
    string $description,
    string $domain,
    string $outputFile = 'og.png'
): string {
    $html = <<<HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      width: 1200px; height: 630px; overflow: hidden;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
      display: flex; align-items: center; justify-content: center; padding: 80px;
    }
    .card { display: flex; flex-direction: column; gap: 24px; width: 100%; }
    .domain {
      font-size: 20px; font-weight: 600; color: #38bdf8;
      text-transform: uppercase; letter-spacing: 2px;
    }
    h1 { font-size: 72px; font-weight: 800; color: #f1f5f9; line-height: 1.1; }
    p { font-size: 28px; color: #94a3b8; line-height: 1.5; }
  </style>
</head>
<body>
  <div class="card">
    <div class="domain">{$domain}</div>
    <h1>{$title}</h1>
    <p>{$description}</p>
  </div>
</body>
</html>
HTML;

    $payload = json_encode(['html' => $html, 'width' => 1200, 'height' => 630, 'format' => 'png']);

    $ch = curl_init('https://renderpix.dev/v1/render');
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $payload,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_HTTPHEADER     => [
            'X-API-Key: rpx_your_api_key',
            'Content-Type: application/json',
        ],
    ]);

    $body   = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($status !== 200) {
        $error = json_decode($body, true);
        throw new RuntimeException("Render failed ({$status}): " . ($error['message'] ?? 'unknown'));
    }

    file_put_contents($outputFile, $body);
    return $outputFile;
}

// Usage
$file = generateOgImage(
    title: 'Build Faster with RenderPix',
    description: 'HTML to image in one API call. No puppeteer, no headless browser.',
    domain: 'renderpix.dev',
);
echo "OG image saved: {$file}\n";
```

---

## Response Handling

A successful render returns the image binary directly (`Content-Type: image/png`).

```php
<?php

$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$ctype  = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); // 'image/png'

if ($status === 200) {
    // $body contains the raw PNG bytes
    file_put_contents('output.png', $body);

    // Or serve directly from a PHP endpoint:
    header('Content-Type: image/png');
    header('Cache-Control: public, max-age=86400');
    echo $body;
    exit;
}
```

---

## Error Handling

```php
<?php

function renderSafe(string $html): ?string
{
    $payload = json_encode(['html' => $html, 'width' => 1200, 'height' => 630]);

    $ch = curl_init('https://renderpix.dev/v1/render');
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $payload,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_HTTPHEADER     => ['X-API-Key: rpx_your_api_key', 'Content-Type: application/json'],
    ]);

    $body    = curl_exec($ch);
    $status  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlErr = curl_error($ch);
    curl_close($ch);

    if ($curlErr) {
        error_log("Network error: {$curlErr}");
        return null;
    }

    $error = json_decode($body, true);

    match ($status) {
        401 => throw new RuntimeException('Invalid API key — check X-API-Key header'),
        429 => throw new RuntimeException('Rate limit exceeded — slow down or upgrade plan'),
        422 => throw new InvalidArgumentException('Invalid request: ' . ($error['message'] ?? '')),
        200 => null, // ok
        default => throw new RuntimeException("Render failed ({$status}): " . ($error['message'] ?? 'unknown')),
    };

    return $body;
}

// Laravel / Symfony — serve as response
$imageBytes = renderSafe('<h1>Hello</h1>');
if ($imageBytes) {
    return response($imageBytes, 200, ['Content-Type' => 'image/png']);
}
```
