1. Go to this page and download the library: Download gosuccess/bunny-api library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
gosuccess / bunny-api example snippets
use GoSuccess\Bunny\Bunny;
$bunny = new Bunny('your-account-api-key');
// Iterate over all pull zones; pages are fetched lazily.
foreach ($bunny->core->pullZones->all() as $pullZone) {
echo $pullZone->name, ': ', $pullZone->originUrl, PHP_EOL;
}
// Purge a URL from the cache.
$bunny->core->purge->url('https://cdn.example.com/styles.css');
use GoSuccess\Bunny\Core\CoreClient;
$core = new CoreClient('your-account-api-key');
$zone = $core->pullZones->get(12345);
use GoSuccess\Bunny\Core\Model\PullZoneCreate;
use GoSuccess\Bunny\Core\Model\PullZoneUpdate;
$zone = $bunny->core->pullZones->create(new PullZoneCreate(
name: 'my-site',
originUrl: 'https://origin.example.com',
));
$bunny->core->pullZones->addHostname($zone->id, 'cdn.example.com');
$bunny->core->pullZones->loadFreeCertificate('cdn.example.com');
$bunny->core->pullZones->setForceSsl($zone->id, 'cdn.example.com', forceSSL: true);
// Change a single setting; everything else stays as it is.
$bunny->core->pullZones->update($zone->id, new PullZoneUpdate(cacheControlMaxAgeOverride: 3600));
// Purge the whole zone, or only the files tagged with a cache tag.
$bunny->core->pullZones->purgeCache($zone->id);
$bunny->core->pullZones->purgeCache($zone->id, cacheTag: 'product-42');
use GoSuccess\Bunny\Core\Enum\EdgeRuleActionType;
use GoSuccess\Bunny\Core\Enum\EdgeRuleTriggerType;
use GoSuccess\Bunny\Core\Enum\PatternMatchingType;
use GoSuccess\Bunny\Core\Enum\TriggerMatchingType;
use GoSuccess\Bunny\Core\Model\EdgeRule;
use GoSuccess\Bunny\Core\Model\EdgeRuleTrigger;
$rule = $bunny->core->edgeRules->addOrUpdate($zone->id, new EdgeRule(
actionType: EdgeRuleActionType::BlockRequest,
triggers: [
new EdgeRuleTrigger(
type: EdgeRuleTriggerType::Url,
patternMatches: ['*/wp-login.php'],
patternMatchingType: PatternMatchingType::MatchAny,
),
],
triggerMatchingType: TriggerMatchingType::MatchAny,
description: 'Block the WordPress login',
enabled: true,
));
// The returned rule carries the GUID bunny.net assigned.
$bunny->core->edgeRules->setEnabled($zone->id, $rule->guid, false);
use GoSuccess\Bunny\Core\Enum\DnsRecordType;
use GoSuccess\Bunny\Core\Model\DnsRecordCreate;
$dnsZone = $bunny->core->dnsZones->create('example.com');
$bunny->core->dnsRecords->create($dnsZone->id, new DnsRecordCreate(
type: DnsRecordType::A,
name: 'www',
value: '203.0.113.10',
ttl: 300,
));
foreach ($bunny->core->dnsRecords->all($dnsZone->id) as $record) {
echo $record->type->name ?? '?', ' ', $record->name, ' ', $record->value, PHP_EOL;
}
// BIND zone files
$zoneFile = $bunny->core->dnsZones->export($dnsZone->id);
$result = $bunny->core->dnsZones->import($dnsZone->id, $zoneFile);
$log = $bunny->logging->logs->legacy($pullZoneId, new DateTimeImmutable('yesterday'));
foreach ($log as $entry) {
// LegacyLogEntry
}
// Keep the raw file:
stream_copy_to_stream($log->stream->resource, fopen('access.log', 'wb'));
use GoSuccess\Bunny\Http\Stream;
use GoSuccess\Bunny\Storage\StorageRegion;
$storage = $bunny->storage('my-zone', 'zone-password', StorageRegion::NewYork);
// Or straight from the Core API, which returns the zone with its passwords:
$storage = $bunny->storageFor($bunny->core->storageZones->get($storageZoneId));
// Upload from a string or, without loading it into memory, from a stream.
$storage->upload('images/logo.png', file_get_contents('logo.png'));
$storage->upload('videos/intro.mp4', Stream::fromFile('intro.mp4'), contentType: 'video/mp4');
// Download into memory or into a stream.
$html = $storage->get('index.html');
$storage->download('backups/db.sql.gz', Stream::fromFile('db.sql.gz', 'wb'));
foreach ($storage->list('images/') as $object) {
echo $object->relativePath, ' ', $object->length, ' bytes', PHP_EOL;
}
$storage->describe('images/logo.png'); // metadata, without downloading
$storage->exists('images/logo.png'); // true or false
$storage->createDirectory('archive/2026');
$storage->delete('images/old.png');
$storage->deleteDirectory('archive'); // with everything in it
use GoSuccess\Bunny\Http\Stream;
use GoSuccess\Bunny\Stream\Model\VideoUpdate;
$stream = $bunny->stream(12345, 'library-api-key');
// Or straight from the Core API, which returns the library with its API keys:
$stream = $bunny->streamFor($bunny->core->videoLibraries->get(12345));
// Create a video, then upload its file; the file is streamed, not loaded into memory.
$video = $stream->videos->create('Product tour');
$stream->videos->upload($video->guid, Stream::fromFile('tour.mp4'), enabledResolutions: ['720p', '1080p']);
// Or let bunny.net download it; returns the GUID of the new video.
$guid = $stream->videos->fetch('https://example.com/tour.mp4', title: 'Product tour');
foreach ($stream->videos->all(search: 'tour') as $video) {
echo $video->title, ': ', $video->status?->name, ', ', $video->views, ' views', PHP_EOL;
}
$stream->videos->update($video->guid, new VideoUpdate(title: 'Product tour 2026'));
$stream->videos->addCaption($video->guid, 'en', Stream::fromFile('tour.en.vtt'), label: 'English');
$stream->videos->useGeneratedThumbnail($video->guid, 3);
$statistics = $stream->statistics->get(dateFrom: new DateTimeImmutable('-7 days'), videoGuid: $video->guid);
use GoSuccess\Bunny\Stream\Upload\TusUpload;
$video = $stream->videos->create('Product tour');
$upload = TusUpload::presign($stream->libraryId, 'library-api-key', $video->guid, new DateTimeImmutable('+1 day'));
// Hand both to a TUS client such as tus-js-client:
$upload->endpoint; // https://video.bunnycdn.com/tusupload
$upload->headers; // AuthorizationSignature, AuthorizationExpire, LibraryId, VideoId
use GoSuccess\Bunny\Stream\Upload\TusSession;
$session = $uploader->create($video->guid, filesize('tour.mp4'), 'video/mp4', 'Product tour');
file_put_contents('upload.json', json_encode($session->toArray()));
// Later, in any process:
$session = TusSession::fromArray(json_decode(file_get_contents('upload.json'), true));
$uploader->resume($session, Stream::fromFile('tour.mp4'));
use GoSuccess\Bunny\Stream\Security\EmbedToken;
$url = EmbedToken::url($libraryId, $videoGuid, 'token-authentication-key', new DateTimeImmutable('+1 hour'), ['autoplay' => true]);
use GoSuccess\Bunny\Exception\InvalidSignatureException;
use GoSuccess\Bunny\Stream\Webhook\WebhookSignature;
use GoSuccess\Bunny\Stream\Webhook\WebhookStatus;
try {
$event = WebhookSignature::parse(file_get_contents('php://input'), getallheaders(), 'library-read-only-api-key');
} catch (InvalidSignatureException) {
http_response_code(401);
exit;
}
if ($event->status === WebhookStatus::Finished) {
// The video $event->videoId is encoded and ready to play.
}
use GoSuccess\Bunny\Shield\Enum\RateLimitAction;
use GoSuccess\Bunny\Shield\Enum\RateLimitBlockTime;
use GoSuccess\Bunny\Shield\Enum\RateLimitCounterKey;
use GoSuccess\Bunny\Shield\Enum\RateLimitTimeframe;
use GoSuccess\Bunny\Shield\Enum\WafRuleOperatorType;
use GoSuccess\Bunny\Shield\Model\RateLimitRuleConfiguration;
$shield = $bunny->shield;
$zone = $shield->zones->getByPullZone($pullZoneId);
echo $zone->planType?->name, ', WAF: ', $zone->wafExecutionMode?->name, PHP_EOL;
// At most 8 login attempts per IP in 10 seconds, then block for a minute.
$shield->rateLimits->create(
shieldZoneId: $zone->shieldZoneId,
ruleName: 'Limit login attempts',
ruleConfiguration: new RateLimitRuleConfiguration(
actionType: RateLimitAction::RateLimit,
variableTypes: ['REQUEST_URI' => ''],
operatorType: WafRuleOperatorType::CONTAINS,
value: 'wp-login',
requestCount: 8,
counterKeyType: RateLimitCounterKey::IP,
timeframe: RateLimitTimeframe::PerTenSeconds,
blockTime: RateLimitBlockTime::ForOneMinute,
),
);
foreach ($shield->eventLogs->all($zone->shieldZoneId, new DateTimeImmutable('yesterday')) as $log) {
echo $log->labels?->country, ' ', $log->labels?->ruleId, PHP_EOL;
}
$metrics = $shield->metrics->overview($zone->shieldZoneId);
use GoSuccess\Bunny\Http\Stream;
use GoSuccess\Bunny\Shield\Model\EventLogFilter;
$top = $shield->eventLogs->search(
$zone->shieldZoneId,
from: new DateTimeImmutable('-1 hour'),
to: new DateTimeImmutable(),
filters: [new EventLogFilter('country', 'in', ['DE', 'AT'])],
groupBy: ['ip'],
);
$shield->eventLogs->export($zone->shieldZoneId, new DateTimeImmutable('-1 day'), new DateTimeImmutable(), sink: Stream::fromFile('events.csv', 'wb'));
use GoSuccess\Bunny\Shield\Enum\AccessListAction;
use GoSuccess\Bunny\Shield\Enum\AccessListType;
$list = $shield->accessLists->create($zone->shieldZoneId, 'Office', AccessListType::CIDR, "203.0.113.0/24\n198.51.100.0/24");
foreach ($shield->accessLists->list($zone->shieldZoneId)->customLists as $details) {
if ($details->listId === $list->id) {
$shield->accessLists->configure($zone->shieldZoneId, $details->configurationId, isEnabled: true, action: AccessListAction::Bypass);
}
}
use GoSuccess\Bunny\Shield\Enum\CustomPageType;
$shield->customPages->upload($zone->shieldZoneId, CustomPageType::Block, file_get_contents('blocked.html'));
use GoSuccess\Bunny\EdgeScripting\Enum\EdgeScriptType;
$scripting = $bunny->edgeScripting;
// CDN is what the dashboard calls a standalone script; DNS and Middleware are the others.
$script = $scripting->scripts->create('hello-edge', EdgeScriptType::CDN, createLinkedPullZone: true);
$scripting->scripts->setCode($script->id, file_get_contents('script.ts'));
$scripting->variables->create($script->id, 'GREETING',
use GoSuccess\Bunny\MagicContainers\Enum\DataGranularity;
$containers = $bunny->magicContainers;
foreach ($containers->apps->all() as $app) {
echo $app->name, ': ', $app->status?->value, PHP_EOL;
}
$app = $containers->apps->get($appId);
$containers->containers->setEnvironmentVariables($appId, $app->containerTemplates[0]->id, ['APP_ENV' => 'production']);
$containers->apps->restart($appId);
$statistics = $containers->apps->statistics($appId, fromDate: new DateTimeImmutable('-1 day'), granularity: DataGranularity::Hourly);
$costs = $containers->apps->summary($appId);
// The IP addresses of all nodes, e.g. for an origin firewall.
$ips = $containers->nodes->plain();
use GoSuccess\Bunny\Core\Model\DnsZoneUpdate;
// Only changes the SOA email; everything else keeps its value.
$bunny->core->dnsZones->update($id, new DnsZoneUpdate(soaEmail: '[email protected]'));
// Sends an explicit null, which clears the value.
$bunny->core->dnsZones->update($id, new DnsZoneUpdate(soaEmail: null));
use GoSuccess\Bunny\Model\Undefined;
new DnsZoneUpdate(soaEmail: $changeEmail ? '[email protected]' : Undefined::Value);
$page = $bunny->core->dnsZones->list(page: 1, perPage: 100);
echo $page->totalItems, ' zones', PHP_EOL;
echo $page->hasMore ? 'more pages follow' : 'last page', PHP_EOL;
foreach ($page->items as $dnsZone) {
// ...
}
// Every zone, fetching pages only while the loop runs:
foreach ($bunny->core->dnsZones->all(search: 'example') as $dnsZone) {
// ...
}
use GoSuccess\Bunny\Bunny;
use GoSuccess\Bunny\ClientOptions;
$bunny = new Bunny('your-account-api-key', new ClientOptions(
timeout: 30.0, // seconds per regular request
connectTimeout: 10.0,
transferTimeout: 0.0, // seconds per streamed up- or download; 0 = no limit
maxRetries: 3,
retryBaseDelay: 1.0, // exponential backoff: 1 s, 2 s, 4 s, ...
maxRetryDelay: 60.0, // also caps a server-provided Retry-After
retryOnRateLimit: true, // false: a 429 throws at once instead of waiting
));
use GoSuccess\Bunny\RateLimit\SlidingWindowRateLimiter;
$bunny = new Bunny('your-account-api-key', rateLimiter: new SlidingWindowRateLimiter(maxRequests: 100, windowSeconds: 60.0));
use GoSuccess\Bunny\Http\HttpClient;
use GoSuccess\Bunny\Http\Request;
use GoSuccess\Bunny\Http\Response;
final class GuzzleTransport implements HttpClient
{
public function send(Request $request): Response { /* ... */ }
}
$bunny = new Bunny('your-account-api-key', httpClient: new GuzzleTransport());
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.