cloudlayerio / cloudlayerio-php
Official PHP SDK for the CloudLayer.io document generation API
v2.0.0
2026-03-17 04:23 UTC
Requires
- php: >=8.1
- guzzlehttp/guzzle: ^7.5
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0
README
Official PHP SDK for the cloudlayer.io document generation API.
Installation
composer require cloudlayerio/sdk
Quick Start
<?php use CloudLayer\CloudLayer; $client = new CloudLayer( apiKey: 'your-api-key', apiVersion: 'v2', ); // Convert a URL to PDF $result = $client->urlToPdf(['url' => 'https://example.com']); // v2 returns a Job — poll until complete, then download $job = $client->waitForJob($result->data->id); $pdfBytes = $client->downloadJobResult($job); file_put_contents('output.pdf', $pdfBytes);
Requirements
- PHP >= 8.1
- ext-json
API Version Differences
| Aspect | v1 | v2 |
|---|---|---|
| Default mode | Synchronous | Asynchronous |
| Sync response | Raw binary (PDF/image bytes) | JSON Job object |
| Async response | JSON Job object | JSON Job object |
| Binary access | Direct from response | downloadJobResult($job) |
v1 Example
$client = new CloudLayer(apiKey: 'key', apiVersion: 'v1'); $result = $client->urlToPdf(['url' => 'https://example.com']); // v1 sync: $result->data is the raw PDF binary file_put_contents('output.pdf', $result->data);
v2 Example
$client = new CloudLayer(apiKey: 'key', apiVersion: 'v2'); $result = $client->urlToPdf(['url' => 'https://example.com']); // v2: $result->data is a Job object $job = $client->waitForJob($result->data->id); $pdfBytes = $client->downloadJobResult($job); file_put_contents('output.pdf', $pdfBytes);
Configuration
$client = new CloudLayer( apiKey: 'your-api-key', // Required apiVersion: 'v2', // Required: 'v1' or 'v2' baseUrl: 'https://api.cloudlayer.io', // Default timeout: 30000, // Request timeout in ms (default: 30000) maxRetries: 2, // Retries for data endpoints (default: 2, max: 5) headers: [], // Additional HTTP headers );
Conversion Methods
URL to PDF / Image
$result = $client->urlToPdf([ 'url' => 'https://example.com', 'printBackground' => true, 'format' => 'a4', 'margin' => ['top' => '1cm', 'bottom' => '1cm'], ]); $result = $client->urlToImage([ 'url' => 'https://example.com', 'imageType' => 'png', 'quality' => 90, ]);
HTML to PDF / Image
HTML content must be Base64-encoded:
$html = base64_encode('<html><body><h1>Hello</h1></body></html>'); $result = $client->htmlToPdf(['html' => $html]); $result = $client->htmlToImage(['html' => $html, 'imageType' => 'png']);
Template Rendering
// By template ID $result = $client->templateToPdf([ 'templateId' => 'your-template-id', 'data' => ['name' => 'John', 'amount' => 99.99], ]); // By raw template (Base64-encoded) $result = $client->templateToPdf([ 'template' => base64_encode('<h1>{{name}}</h1>'), 'data' => ['name' => 'John'], ]);
File Conversion
// DOCX to PDF (file path) $result = $client->docxToPdf(['file' => '/path/to/document.docx']); // PDF to DOCX (raw content) $result = $client->pdfToDocx(['file' => file_get_contents('input.pdf')]); // DOCX to HTML $result = $client->docxToHtml(['file' => '/path/to/document.docx']);
PDF Merge
$result = $client->mergePdfs([ 'url' => 'https://example.com/doc1.pdf', ]);
Batch Processing
$result = $client->urlToPdf([ 'batch' => ['urls' => [ 'https://example.com/page1', 'https://example.com/page2', 'https://example.com/page3', ]], ]);
Async Mode & Job Polling
// v2 defaults to async $result = $client->urlToPdf(['url' => 'https://example.com']); // Poll until the job completes (default: 5s interval, 5min timeout) $job = $client->waitForJob($result->data->id, [ 'interval' => 5000, // Poll every 5 seconds (minimum: 2000ms) 'maxWait' => 300000, // Give up after 5 minutes ]); // Download the result $binary = $client->downloadJobResult($job);
Data Management
// Jobs (WARNING: listJobs returns ALL jobs — no pagination) $jobs = $client->listJobs(); $job = $client->getJob('job-id'); // Assets (WARNING: listAssets returns ALL assets — no pagination) $assets = $client->listAssets(); $asset = $client->getAsset('asset-id'); // Storage $storageList = $client->listStorage(); $storage = $client->getStorage('storage-id'); $result = $client->addStorage(new \CloudLayer\Types\StorageParams( title: 'My S3 Bucket', region: 'us-east-1', accessKeyId: 'AKIA...', secretAccessKey: 'secret', bucket: 'my-bucket', )); $client->deleteStorage('storage-id'); // Account $account = $client->getAccount(); $status = $client->getStatus(); // Public Templates (always v2, no auth required) $templates = $client->listTemplates(['type' => 'invoice']); $template = $client->getTemplate('template-id');
Error Handling
use CloudLayer\Errors\CloudLayerException; use CloudLayer\Errors\ConfigException; use CloudLayer\Errors\ValidationException; use CloudLayer\Errors\AuthException; use CloudLayer\Errors\RateLimitException; use CloudLayer\Errors\ApiException; use CloudLayer\Errors\TimeoutException; use CloudLayer\Errors\NetworkException; try { $result = $client->urlToPdf(['url' => 'https://example.com']); } catch (AuthException $e) { // 401/403 — invalid or missing API key echo "Auth error: {$e->getMessage()}\n"; } catch (RateLimitException $e) { // 429 — rate limited, retry after $e->retryAfter seconds echo "Rate limited. Retry after {$e->retryAfter}s\n"; } catch (TimeoutException $e) { // Request timed out echo "Timeout after {$e->timeout}ms\n"; } catch (NetworkException $e) { // DNS failure, connection refused, etc. echo "Network error: {$e->getMessage()}\n"; } catch (ApiException $e) { // Other API errors (4xx/5xx) echo "API error {$e->status}: {$e->getMessage()}\n"; } catch (ValidationException $e) { // Client-side validation failure echo "Invalid {$e->field}: {$e->getMessage()}\n"; } catch (ConfigException $e) { // Invalid client configuration echo "Config error: {$e->getMessage()}\n"; }
Performance Notes
listJobs()/listAssets(): Return ALL records with no pagination. Each call reads every document from the database. UsegetJob()/getAsset()for single lookups.waitForJob()polling: Each poll reads one database document. Default 5-second interval is intentional — don't decrease below 2 seconds.- Conversion requests are not retried: Conversions are expensive server-side operations. Only data management GET endpoints are automatically retried on 429/5xx.
Type Safety
The SDK uses declare(strict_types=1) in every file and passes PHPStan level 8 (maximum strictness). All response types are readonly value objects with typed properties.
Other SDKs
- JavaScript/TypeScript: @cloudlayerio/sdk (GitHub)
- Python: cloudlayerio (GitHub)
- Go: cloudlayerio-go (GitHub)
- .NET C#: cloudlayerio-dotnet (GitHub)