Official PHP SDK for Bannerify - Generate images and PDFs at scale via API.
Install via Composer:
composer require bannerify/bannerify<?php
require 'vendor/autoload.php';
use Bannerify\Client;
// Create client with your API key
$client = new Client('your-api-key');
// Generate an image
$result = $client->createImage('tpl_xxxxxxxxx', [
'modifications' => [
['name' => 'title', 'text' => 'Hello World'],
['name' => 'subtitle', 'text' => 'From PHP SDK']
]
]);
if (isset($result['result'])) {
file_put_contents('output.png', $result['result']);
echo "Image created successfully!";
} else {
echo "Error: " . $result['error']['message'];
}- 🚀 Simple, intuitive API
- 🔒 Type-safe with PHPStan support
- ⚡ Built on Guzzle for reliability
- 🎯 Result/Error pattern for explicit error handling
- 📝 Comprehensive documentation
- ✅ Well-tested
// Generate PNG
$result = $client->createImage('tpl_xxxxxxxxx', [
'modifications' => [
['name' => 'title', 'text' => 'My Title'],
['name' => 'image', 'src' => 'https://example.com/image.jpg']
]
]);
// Generate WebP
$result = $client->createImage('tpl_xxxxxxxxx', [
'format' => 'webp',
'modifications' => [
['name' => 'title', 'text' => 'My Title']
]
]);A modification can also be a Bannerify\Types\Modification object. The SDK leaves out every field that is null:
use Bannerify\Types\Modification;
$result = $client->createImage('tpl_xxxxxxxxx', [
'modifications' => [
new Modification(name: 'title', text: 'My Title'),
new Modification(name: 'image', src: 'https://example.com/image.jpg'),
]
]);$result = $client->createPdf('tpl_xxxxxxxxx', [
'modifications' => [
['name' => 'title', 'text' => 'Invoice #123']
]
]);
if (isset($result['result'])) {
file_put_contents('invoice.pdf', $result['result']);
}$signedUrl = $client->generateImageSignedUrl('tpl_xxxxxxxxx', [
'modifications' => [
['name' => 'title', 'text' => 'Dynamic Title']
],
'format' => 'png'
]);
// Use in HTML
echo "<img src='{$signedUrl}' alt='Generated Image' />";A video template renders as an MP4. Each second of the video counts as one generation, and as two at 60 fps.
// Follow the render: created, queued, progress, then done or error
foreach ($client->renderVideo('tpl_xxxxxxxxx', ['modifications' => [['name' => 'title', 'text' => 'Hi']]]) as $event) {
match ($event['type']) {
'progress' => printf("%d%%\n", $event['progress'] * 100),
'done' => print($event['url'] . "\n"),
'error' => print($event['error']['message'] . "\n"),
default => null,
};
}
// Or wait for the URL of the MP4
$result = $client->renderAndWaitVideo('tpl_xxxxxxxxx');The created event gives the id of the video. The video renders to its end even when the connection drops. Then renderVideo reads the same video again by its id: it waits 1, 2, 4 and 8 seconds before each of 4 attempts, and it never sends the render again. When the attempts run out, the last event is an error with the code TIMEOUT_ERROR.
// Start the video and get its id at once, without waiting
$created = $client->createVideo('tpl_xxxxxxxxx'); // ['result' => ['id', 'status' => 'queued']] or ['error' => [...]]createVideo sends the render once and never again, because a second request renders a second video.
// Read the video later by its id
$video = $client->getVideo('vid_xxx'); // ['result' => ['id', 'status', 'url']] or ['error' => [...]]
// Follow its events again, from the latest one
foreach ($client->watchVideo('vid_xxx') as $event) {
echo $event['type'] . "\n";
}$result = $client->createImage('tpl_xxxxxxxxx');
if (isset($result['error'])) {
$error = $result['error'];
echo "Error Code: " . $error['code'] . "\n";
echo "Message: " . $error['message'] . "\n";
echo "Docs: " . $error['docs'] . "\n";
} else {
file_put_contents('output.png', $result['result']);
}new Client(string $apiKey, array $options = [])Options:
baseUrl(string): API base URLtimeout(float): Request timeout in seconds
createImage(string $templateId, array $options = []): arrayOptions:
modifications(array): Array of modificationsformat(string): 'png', 'jpeg', or 'webp'
Returns: Array with result (string) or error (array)
createPdf(string $templateId, array $options = []): arraycreateStoredImage(string $templateId, array $options = []): arrayrenderVideo(string $templateId, array $options = []): GeneratorYields ['type' => 'created', 'id'], ['type' => 'queued', 'ahead'], ['type' => 'progress', 'frame', 'totalFrames', 'progress'], then ['type' => 'done', 'url'] or ['type' => 'error', 'error'].
renderAndWaitVideo(string $templateId, array $options = []): arraywatchVideo(string $id): GeneratorYields the events of renderVideo again, from the latest one, without created.
createVideo(string $templateId, array $modifications = []): arrayStarts the video and returns ['result' => ['id', 'status' => 'queued']] or ['error' => [...]] at once.
getVideo(string $id): arrayReturns ['result' => ['id', 'status', 'url'?, 'error'?]] or ['error' => [...]]. status is queued, rendering, done or failed.
generateImageSignedUrl(string $templateId, array $options = []): string$products = [
['name' => 'Product A', 'price' => '$29.99'],
['name' => 'Product B', 'price' => '$39.99'],
];
foreach ($products as $i => $product) {
$result = $client->createImage('tpl_product_banner', [
'modifications' => [
['name' => 'product_name', 'text' => $product['name']],
['name' => 'price', 'text' => $product['price']]
]
]);
if (isset($result['result'])) {
file_put_contents("banner_{$i}.png", $result['result']);
}
}foreach ($recipients as $recipient) {
$signedUrl = $client->generateImageSignedUrl('tpl_email_header', [
'modifications' => [
['name' => 'name', 'text' => "Hi, {$recipient['name']}!"]
]
]);
// Use $signedUrl in email HTML
}Full documentation available at https://bannerify.co/docs/sdk/php/overview
- Documentation: https://bannerify.co/docs
- Issues: https://github.com/bannerify/bannerify-php/issues
- Email: support@bannerify.co
MIT License - see LICENSE file for details