Skip to content
Cloudflare Docs

Managing Workers with the API and IaC

Uploading and managing a Worker is easy with Wrangler, but sometimes you need to do it more programmatically or scalably. You might do this with IaC ("Infrastructure as Code") tools or by calling the Cloudflare API directly. Use cases for the API include build and deploy scripts, CI/CD pipelines, custom dev tools, or testing. We provide API SDK libraries for common languages that make interacting with the API easier, such as cloudflare-typescript. For IaC, a common tool is HashiCorp's Terraform. You can use the Cloudflare Terraform Provider to create and manage Workers resources.

Examples

Here are examples of uploading a Worker script with common tools and languages. In particular, they highlight how to upload script content and format multipart upload metadata which is different with each approach.

curl

Open a terminal or create a shell script to upload a Worker easily with curl. For this example, replace <account_id> with your account id and <api_token> with an API token (not Global API key). Reference the Upload Worker Module API docs here.

Terminal window
curl https://api.cloudflare.com/client/v4/accounts/<account_id>/workers/scripts/my-hello-world-script \
-X PUT \
-H 'Authorization: Bearer <api_token>' \
-F 'metadata={
"main_module": "my-hello-world-script.mjs",
"bindings": [
{
"type": "plain_text",
"name": "MESSAGE",
"text": "Hello World!"
}
],
"compatibility_date": "2025-03-11"
};type=application/json' \
-F 'my-hello-world-script.mjs=@-;filename=my-hello-world-script.mjs;type=application/javascript+module' <<EOF
export default {
async fetch(request, env, ctx) {
return new Response(env.MESSAGE, { status: 200 });
}
};
EOF

JavaScript/TypeScript

This example uses the cloudflare-typescript library which provides convenient access to the Cloudflare REST API from server-side JavaScript or TypeScript.

#!/usr/bin/env -S npm run tsn -T
/*
* Generate an API token: https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
* (Not Global API Key!)
*
* Find your account id: https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/
*
* Set these environment variables:
* - CLOUDFLARE_API_TOKEN
* - CLOUDFLARE_ACCOUNT_ID
*/
import Cloudflare from "cloudflare";
const client = new Cloudflare({
apiToken: process.env["CLOUDFLARE_API_TOKEN"] ?? "",
});
const accountID = process.env["CLOUDFLARE_ACCOUNT_ID"] ?? "";
async function main() {
const scriptName = "my-hello-world-script";
const scriptFileName = `${scriptName}.mjs`;
const scriptContent = `
export default {
async fetch(request, env, ctx) {
return new Response(env.MESSAGE, { status: 200 });
}
};
`;
const script = await client.workers.scripts.update(scriptName, {
account_id: accountID,
/*
* Add script content keyed by the filename
*/
// @ts-ignore
[scriptFileName]: new File([scriptContent], scriptFileName, {
type: "application/javascript+module",
}),
// @ts-ignore
metadata: new File(
[
JSON.stringify({
// https://developers.cloudflare.com/workers/configuration/multipart-upload-metadata/
bindings: [
{
type: "plain_text",
name: "MESSAGE",
text: "Hello World!",
},
],
main_module: scriptFileName,
}),
],
"metadata.json",
{
type: "application/json",
},
),
});
console.log(script.id);
}
main();

Terraform

In this example, you need a local file named my-hello-world-script.mjs with script content similar to the above examples. Replace account_id with your own. Learn more about the Cloudflare Terraform Provider here.

terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 5"
}
}
}
resource "cloudflare_workers_script" "my-hello-world-script" {
account_id = "<replace_me>"
script_name = "my-hello-world-script"
main_module = "my-hello-world-script.mjs"
content = trimspace(file("my-hello-world-script.mjs"))
bindings = [{
name = "MESSAGE"
type = "plain_text"
text = "Hello World!"
}]
}