PHP code example of gosuccess / bunny-api

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);

$statistics = $bunny->core->statistics->get(
    dateFrom: new DateTimeImmutable('-7 days'),
    pullZone: $zone->id,
    hourly: true,
);

echo $statistics->totalBandwidthUsed, ' bytes, cache hit rate ', $statistics->cacheHitRate, ' %', PHP_EOL;

foreach ($statistics->bandwidthUsedChart as $hour => $bytes) {
    // ...
}

$log = $bunny->originErrors->get($pullZoneId, new DateTimeImmutable('yesterday'));

foreach ($log->errors as $error) {
    echo $error->timestamp->format('H:i:s'), ' ', $error->statusCode, ' ', $error->errorCode, ' ', $error->requestUrl, PHP_EOL;
}

foreach ($bunny->logging->logs->all($pullZoneId, from: new DateTimeImmutable('-24 hours'), status: '4xx,5xx', country: 'DE') as $entry) {
    echo $entry->timestamp->format(DATE_ATOM), ' ', $entry->statusCode, ' ', $entry->url, PHP_EOL;
}

$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\Http\Stream;

$video = $stream->videos->create('Product tour');
$uploader = $bunny->streamUploader(12345, 'library-api-key');

$uploader->upload(
    $video->guid,
    Stream::fromFile('tour.mp4'),
    fileType: 'video/mp4',
    title: 'Product tour',
    onProgress: static function (int $sent, int $total): void {
        echo round($sent / $total * 100), '%', PHP_EOL;
    },
);

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\Exception\NotFoundException;

try {
    $bunny->core->pullZones->get(12345);
} catch (NotFoundException $e) {
    echo $e->getMessage(), ' (', $e->errorKey, ')', PHP_EOL;
}

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());