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";
}A signed URL of a video template plays the video without a request from your server. The video link (m3u8, the default) is an HLS playlist: it starts to play while the video renders, and plays at once when the same video rendered before. An edit renders again only the seconds it changes. mp4 redirects to the MP4 once it rendered, for videos of up to 15 seconds. Video links are for the Scale and Enterprise plans.
$videoUrl = $client->generateVideoSignedUrl('tpl_xxxxxxxxx', [
'modifications' => [
['name' => 'title', 'text' => 'Dynamic Title']
],
]);
// Safari plays HLS in a <video>; other browsers need an HLS player such as hls.js
echo "<video src='{$videoUrl}' controls></video>";
$mp4Url = $client->generateVideoSignedUrl('tpl_xxxxxxxxx', ['format' => 'mp4']);$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 = []): stringgenerateVideoSignedUrl(string $templateId, array $options = []): string // format: 'm3u8' (the default) or 'mp4'$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