Exploring the resource API
The client has accessors for accounts(), zones(), workers(), r2(), kv(), d1(), queues(), hyperdrive(), and secrets_store(). Each returns a small resource object tied to the same client and token. The examples below show representative operations rather than every method.
Lists, detail, and changes
Most resources offer a familiar list, get, create, update, and delete pattern. For example, you can list R2 buckets, get one by name, then update or delete it using that name. Queues, Hyperdrive configurations, and Secrets Store resources follow the same general pattern, with bodies specific to the Cloudflare endpoint.
my $bucket_hr=$api_or->r2()->get_bucket('my-app-assets');
my $queue_hr=$api_or->queues()->create_queue({ queue_name => 'jobs' });
my $config_ar=$api_or->hyperdrive()->list_configs();
Accounts and zones are useful starting points when you do not yet know an ID:
my $accounts_ar=$api_or->accounts()->list();
my $zones_ar=$api_or->zones()->list(name => 'example.com');
The methods that take a body pass the supplied hash reference to Cloudflare. Refer to the relevant Cloudflare API endpoint for its required fields and accepted values. The module deliberately leaves most endpoint-specific payload choices with the caller.
KV values and D1 queries
KV has a small convenience API for keys and raw values. The value methods are separate from the JSON management methods because the value body need not be JSON:
my $kv_or=$api_or->kv();
$kv_or->put_value('namespace-id', 'greeting', 'Hello', expiration_ttl => 3600);
my $value=$kv_or->get_value('namespace-id', 'greeting');
my $keys_ar=$kv_or->list_keys('namespace-id', prefix => 'greet');
get_value() returns raw bytes. put_value() accepts either expiration or expiration_ttl, and writing a value replaces its previous expiration and metadata. It does not support metadata-bearing writes through this convenience method.
For D1, query_sql() keeps SQL parameters separate from the statement:
my $rows_ar=$api_or->d1()->query_sql(
'database-id',
'SELECT id, name FROM people WHERE id = ?',
[42]
);
The D1 REST result remains Cloudflare's array of query results. This is a management API call, not a DBI connection or a migration tool. Hyperdrive methods likewise manage connection configuration; SQL for a Hyperdrive-backed application goes through a Worker binding and database driver.
Worker scripts, versions, and assets
To upload a Worker, prepare its module files first. The metadata must identify a main_module whose name matches one of the supplied file entries. Each entry may contain a local path or in-memory content. This example uploads an already built module:
my $worker_hr=$api_or->workers()->upload_script('my-app',
metadata => {
main_module => 'worker.mjs',
compatibility_date => '2026-09-22',
bindings => [
{ type => 'r2_bucket', name => 'ASSETS',
bucket_name => 'my-app-assets' }
]
},
files => [
{ name => 'worker.mjs', path => 'dist/worker.mjs' }
]
);
Warning
upload_script() deploys immediately. If you want to inspect a version
before activating it, use upload_version() with the same metadata and
files arguments, then call create_deployment() when you are ready.
Static assets can be uploaded from a directory, a list of files, or a URL-path map. The returned value includes a manifest and a short-lived completion JWT for the version metadata:
my $assets_hr=$api_or->workers()->upload_assets(
'my-app', 'dist/site', prefix => '/docs'
);
my $version_hr=$api_or->workers()->upload_version('my-app',
metadata => {
main_module => 'worker.mjs',
compatibility_date => '2026-09-22',
assets => { jwt => $assets_hr->{'jwt'} },
bindings => [{ type => 'assets', name => 'ASSETS' }]
},
files => [{ name => 'worker.mjs', path => 'dist/worker.mjs' }]
);
Neither upload_assets() nor upload_version() activates a new deployment. Asset uploads are assembled in memory, so consider the size of the files in a large upload. Treat the completion JWT as a credential and keep it out of logs. Worker routes use a zone ID; script upload does not create a route automatically.
Other Worker methods inspect scripts and versions, manage deployments and secret bindings, and control routes or the workers.dev subdomain. download_script() returns a raw response because its body is source content. Secret values are write-only; do not expect a later list or get call to return them.