ConicPlex

Start Your Project

A stylized orange cloud illustration with a key icon and circuit-line accents, representing Cloudflare API authentication

On this Page

How to Create a Cloudflare Workers Build Token Using the API

Cloudflare’s Workers Builds API asks for build_token_secret and cloudflare_token_id but never explains where those values come from. Here is the exact mapping.

Sajil Memon

August 19, 2026

Cloudflare’s Workers Builds API asks for three fields when you create a build token: build_token_name, build_token_secret, and cloudflare_token_id. The API reference lists them as required strings but never explains where the last two values actually come from. Here’s the mapping: build_token_secret is your existing Cloudflare API token’s secret, not a random string you invent, and cloudflare_token_id is the result.id field returned by Cloudflare’s own token verification endpoint. Get those two values right and the request works on the first try.

We ran into this while wiring up CI/CD for a client’s Worker deployment as part of a broader web application development engagement. The example payload in Cloudflare’s docs uses placeholder values like super-secret-token and cf-token-123, which look like something you’re supposed to generate yourself. Even AI coding assistants tend to read it that way and suggest a random UUID. Neither is correct, and the 400 error you get back doesn’t say why. This post is the missing context.

The Create Build Token Endpoint

The endpoint is:

POST https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/builds/tokens

It needs a Bearer token in the Authorization header and returns a build token you’ll use later when setting up a Workers Builds trigger. Cloudflare’s own reference for this endpoint confirms the three required body fields but stops short of explaining the relationship between build_token_secret, cloudflare_token_id, and the Cloudflare API token you already have sitting in your dashboard.

Step 1: Get Your Account ID

You need your Cloudflare Account ID for the URL itself. Fastest way to find it:

  1. Log in to the Cloudflare dashboard.
  2. Press Cmd+K on macOS or Ctrl+K on Windows/Linux to open the command palette.
  3. Type “Account ID.”
  4. Click the result to copy it.

Drop it into the URL:

https://api.cloudflare.com/client/v4/accounts/1234567890abcdef1234567890abcdef/builds/tokens

Step 2: Authenticate the Request

Send your Cloudflare API token as a Bearer token, plus a JSON content type:

Authorization: Bearer cfut_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

This is the same API token you’d use for any other Cloudflare API call. Cloudflare recommends scoped API tokens over the legacy global API key for exactly this kind of automation, and Workers Builds is no exception.

What Does build_token_name Actually Need?

Nothing tricky here. It’s a plain descriptive label:

{
  "build_token_name": "ConicPlex Production Build Token"
}

Name it whatever helps you tell tokens apart later: “Production Build Token,” “Client Deployment CI/CD,” “Nuxt Production Build.” It’s cosmetic, and it’s the one field in this whole flow that behaves exactly the way it reads.

What Does build_token_secret Actually Need?

This is where the confusion starts. Cloudflare’s example body shows:

"build_token_secret": "super-secret-token"

which reads like a placeholder you’re meant to swap for a random string of your own choosing. It isn’t. The value should be the secret of the actual Cloudflare API token you’re associating with this build token, the same cfut_... value you’re already sending in the Authorization header:

{
  "build_token_secret": "cfut_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Don’t generate a UUID for this field just because the key is named “secret.” The API reference defines it as a required string without clarifying that relationship, which is the single biggest source of confusion in the whole flow. If you send a made-up value here, the request will either fail outright or create a token that’s disconnected from the API token you actually intended to use.

What Does cloudflare_token_id Actually Need?

The second field trips people up just as often:

"cloudflare_token_id": "cf-token-123"

It is not your Account ID, and it is not the token secret you just used above. It’s the identifier of your Cloudflare API token, and you get it from a completely different endpoint: Cloudflare’s token verification API.

How Do You Get cloudflare_token_id?

Call the verify endpoint with the same API token:

curl "https://api.cloudflare.com/client/v4/user/tokens/verify" \
  --header "Authorization: Bearer YOUR_CLOUDFLARE_API_TOKEN"

The response includes an id field, which Cloudflare’s docs label the token’s identifier tag:

{
  "success": true,
  "result": {
    "id": "d3049b00a220a67a31c9bf3cd79a036a",
    "status": "active"
  },
  "errors": [],
  "messages": []
}

That result.id value is what goes into cloudflare_token_id.

Putting the Full Request Together

With all three values sorted, the request body looks like this:

POST https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/builds/tokens

Headers:
Authorization: Bearer YOUR_CLOUDFLARE_API_TOKEN
Content-Type: application/json

Body:
{
  "build_token_name": "ConicPlex Production Build Token",
  "build_token_secret": "cfut_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "cloudflare_token_id": "d3049b00a220a67a31c9bf3cd79a036a"
}

A successful call returns the created token’s details:

{
  "success": true,
  "errors": [],
  "messages": [],
  "result": {
    "build_token_name": "ConicPlex Production Build Token",
    "build_token_uuid": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
    "cloudflare_token_id": "d3049b00a220a67a31c9bf3cd79a036a",
    "owner_type": "user"
  }
}

Hold onto build_token_uuid. That’s the value you’ll pass in when creating a Workers Builds CI/CD trigger, which is the whole point of generating this token in the first place.

Don’t Mix Up the Four Different IDs

Workers CI/CD involves more identifiers than the docs make obvious, and they’re easy to confuse under deadline pressure:

ID What it identifies Where it comes from
Account ID Your Cloudflare account Dashboard command palette (Cmd/Ctrl+K)
cloudflare_token_id Your Cloudflare API token result.id from /user/tokens/verify
build_token_uuid The Workers Build Token itself Returned when you create the build token
Worker Tag The Worker script tied to the build Workers dashboard / scripts API

None of these are interchangeable, and the API won’t warn you if you swap one for another. It’ll usually just fail with an error that doesn’t point back to which field was wrong.

Treat the API Token Secret Like Any Other Credential

Because build_token_secret is your real Cloudflare API token, it deserves the same handling as a database password or a signing key. Keep it out of:

  • GitHub repositories, public or private
  • Client-side JavaScript, including Vue and Nuxt front-end code
  • Public documentation or internal wikis without access controls
  • Screenshots shared in tickets or Slack

Store it in environment variables or a secret manager instead:

CLOUDFLARE_API_TOKEN=cfut_xxxxxxxxx
CLOUDFLARE_ACCOUNT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Cloudflare only shows a token’s secret once, at creation time. If you lose it, the fix is generating a new token, not recovering the old one.

Frequently Asked Questions

Is build_token_secret the same as my Cloudflare API token?

Yes. It’s the secret value of the Cloudflare API token you’re associating with the build token, the exact same string you send as a Bearer token in the Authorization header. It is not a value you generate yourself.

What’s the difference between cloudflare_token_id and my Account ID?

They identify completely different things. Account ID identifies your Cloudflare account and comes from the dashboard. cloudflare_token_id identifies a specific API token and comes from calling /user/tokens/verify and reading result.id.

Why does the Create Build Token API return a 400 error with no clear reason?

The most common cause is sending a random or made-up value for build_token_secret or cloudflare_token_id instead of the real values described above. Double-check both against your actual API token before assuming the request format itself is wrong.

Where do I use build_token_uuid after I get it?

It’s the value the Workers Builds trigger API expects when you connect a repository to CI/CD, so the build system knows which token authorizes that pipeline.

Sources

Sajil Memon is a co-founder of ConicPlex and a Senior Full Stack Developer focused on backend work: Node.js, PHP, APIs, and the infrastructure decisions that determine whether a system holds up under real traffic. He’s spent years on the side of a project that doesn’t get demoed, the part that has to keep working after launch. He writes here about the technical tradeoffs in backend architecture, deployment, and data handling that only become obvious once something breaks in production.

Keep reading

News & Updates

A laptop and an antique analog monitoring gauge glowing blue on a dark desk at night, symbolizing a quietly exploited server monitoring vulnerability

Zimbra Collaboration Suite RCE Flaw Faces Active Exploitation (CVE-2026-73570)

CISA added Zimbra Collaboration Suite flaw CVE-2026-73570 to its Known Exploited Vulnerabilities catalog on August 21, 2026, confirming active attacks…

Sameer Malek

August 22, 2026

Design

A laptop displaying a dark navy financial dashboard with charts, next to a leather portfolio and fountain pen on an office desk

What Actually Makes a Finance Website Look Trustworthy

A finance website earns trust through specific, checkable signals: named credentials, transparent pricing or process language, fast load times, and…

Hasnain Memon

August 22, 2026

Software

A phone glowing with a notification next to a laptop showing a CRM dashboard on a dealership office desk at dusk, with a car visible through the window

Speed to Lead: Why Your Website’s Tools Need to Feed Your CRM in Real Time

A real WordPress plugin build shows why on-site interactive tools should feed your CRM in real time, not an inbox,…

Sajil Memon

August 22, 2026