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_IDandCLOUDFLARE_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.
- Open the Cloudflare dashboard and go to Account home.
- Select Search, or press
Ctrl+K(Cmd+Kon a Mac). - Enter
Copy account IDand 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.
- Go to My Profile > API Tokens and select Create Token.
- In the Custom token section, click Get started beside Create Custom Token.
- Under Token name, enter
hello-worker. - Under Permissions, add a row for each permission in the table below. Use Add more to start each new row.
- 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.
- Under Account Resources, keep Include and choose your account.
- Select Continue to summary, review the five permissions, and finish with Create Token.
- Copy the token. The same page has a
curlcommand 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.
In
hello-worker, create.envwith your account ID and scoped token:CLOUDFLARE_ACCOUNT_ID= CLOUDFLARE_API_TOKEN=Add
.envto the application's.gitignore, and restrict its permissions:printf '\n.env\n' >> .gitignore chmod 600 .envIf 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.