Skip to content

Credentials

Your F# programs call Cloudflare's API with two values: your account ID and an API token. You find both in the Cloudflare dashboard, and your programs read them from environment variables.

  • You need A Cloudflare account
  • You get CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN, kept in .env

Account ID

The account ID identifies your Cloudflare account. Most account-level operations in the generated clients take it as an accountId argument, StorageClient.D1CreateDatabase among them.

  1. Open the Cloudflare dashboard and go to Account home.
  2. Select Search, or press Ctrl+K (Cmd+K on a Mac).
  3. Enter Copy account ID and choose the result. The ID is now on your clipboard.

The Account Details section of Workers & Pages shows the same ID, with a copy button beside Account ID.

Scoped API Token

Your programs send the token with every request, and Cloudflare checks each request against the token's permissions. Create a user token with the five permissions that the later examples require.

  1. Go to My Profile > API Tokens and select Create Token.
  2. In the Custom token section, click Get started beside Create Custom Token.
  3. Under Token name, enter hello-worker.
  4. Under Permissions, add a row for each permission in the table below. Use Add more to start each new row.
  5. In each row, set the first menu to Account and the last one to Edit. In the middle menu, pick the permission group from the table, such as D1.
  6. Under Account Resources, keep Include and choose your account.
  7. Select Continue to summary, review the five permissions, and finish with Create Token.
  8. Copy the token. The same page has a curl command in its Test this token section. Run it. A reply with "status": "active" means the token works.

Token Permissions

All five are Account permissions at the Edit level. On the API tab of Cloudflare's permissions reference, the same permission names end in Write where the dashboard uses Edit.

Permission Covers Used on
D1 Edit D1 databases Account Setup
Workers R2 Storage Edit R2 buckets Account Setup
Workers KV Storage Edit KV namespaces Account Setup
Queues Edit Queues Account Setup
Workers Scripts Edit Worker scripts Worker Upload, First Deploy

Other operations in the generated clients may require other permissions. You can add them later, since Cloudflare lets you edit an existing token.

Token Safety

  • Use a scoped token, never the Global API Key. That key has the same permissions as your user, on all of your resources. Anyone holding your new token can perform the actions its five permissions grant.
  • Keep tokens out of source control. The token belongs in .env, which you must exclude in your application’s .gitignore. GitHub scans public repositories for Cloudflare tokens. When it finds one, Cloudflare revokes the token and notifies you by email.
  • Roll a lost or leaked token. On My Profile > API Tokens, open the three-dot menu next to the token and choose Roll, then Confirm. Cloudflare invalidates the old secret, and the new one has the same permissions.

The .env File

Keep credentials in the hello-worker application folder from First Worker. Complete these steps before First Deploy; a library source checkout is not required.

  1. In hello-worker, create .env with your account ID and scoped token:

    CLOUDFLARE_ACCOUNT_ID=
    CLOUDFLARE_API_TOKEN=
    
  2. Add .env to the application's .gitignore, and restrict its permissions:

    printf '\n.env\n' >> .gitignore
    chmod 600 .env
    
  3. If the application is in a Git repository, confirm that the file is ignored:

    git check-ignore .env
    

Shell Variables

Environment.GetEnvironmentVariable reads the environment that your terminal passes to each program it starts. Load .env into that environment from the hello-worker folder.

set -a
source .env
set +a

set -a marks every variable that source reads from .env for export, and set +a turns the marking off. Check the result:

printenv CLOUDFLARE_ACCOUNT_ID

It prints your account ID. If the output is empty, check that you saved your account ID in .env, then run the three lines again in this terminal.

In each new terminal, load .env again from your hello-worker folder:

set -a
source .env
set +a

Client Setup

Every generated client takes an HttpClient. cloudflareHttp returns one with Cloudflare's API base address and your token in its Authorization header. When a variable is missing, fromEnvironment reports the name and exits.

module ClientSetup

open System
open System.Net.Http
open System.Net.Http.Headers

let fromEnvironment name =
    match Environment.GetEnvironmentVariable name with
    | null | "" ->
        eprintfn "%s is not set. Load .env into this terminal first." name
        exit 1
    | value -> value

let accountId () = fromEnvironment "CLOUDFLARE_ACCOUNT_ID"

let cloudflareHttp () =
    let token = fromEnvironment "CLOUDFLARE_API_TOKEN"
    let http = new HttpClient()
    http.BaseAddress <- Uri "https://api.cloudflare.com/client/v4"
    let headers = http.DefaultRequestHeaders
    headers.Authorization <- AuthenticationHeaderValue("Bearer", token)
    http

A program that calls cloudflareHttp before you load .env prints this line:

CLOUDFLARE_API_TOKEN is not set. Load .env into this terminal first.

Token Check

UserApiTokensVerifyToken on the Tenancy client sends GET /user/tokens/verify, the same request as the Test this token command. The result is a union. OK holds the reply to HTTP 200, and Status4XX holds the status code and Cloudflare's errors for a 4xx response. checkToken takes the HttpClient from Client Setup.

module TokenCheck

open System.Net.Http
open FSharp.CloudEdge.Core.Api.Types
open FSharp.CloudEdge.Tenancy

let checkToken (http: HttpClient) =
    task {
        let tenancy = TenancyClient http
        match! tenancy.UserApiTokensVerifyToken() with
        | UserApiTokensVerifyToken.OK payload ->
            let tokenStatus =
                match payload.result with
                | Some result -> string result["status"]
                | None -> "unknown"
            printfn "Token status: %s" tokenStatus
            return tokenStatus = "active"
        | UserApiTokensVerifyToken.Status4XX(httpStatus, failure) ->
            for error in failure.errors do
                eprintfn "HTTP %d: %s" httpStatus error.message
            return false
    }

With a working token, checkToken returns true, and the output is:

Token status: active

For a rejected token, the Status4XX branch prints the HTTP status with each error message from Cloudflare's reply, and checkToken returns false.

Next Step

Edit this page