Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 81 additions & 29 deletions alchemy-web/src/content/docs/providers/cloudflare/account-api-token.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
---
title: AccountApiToken
description: Learn how to create and manage Cloudflare Account API Tokens using Alchemy for secure access to the Cloudflare API.
description: Learn how to create and manage Cloudflare Account API Tokens using Alchemy for secure access to the Cloudflare API and R2 storage.
---

Creates a [Cloudflare API Token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with specified permissions and access controls.
Creates a [Cloudflare API Token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with specified permissions and access controls. Account API Tokens are the primary way to generate S3-compatible credentials for R2 storage, enabling pre-signed URLs and direct S3 API access.

:::caution
Account API Tokens can not be created with OAuth tokens because of a Cloudflare limitation. use the Global API Key or an API Token instead. See the [Cloudflare Auth guide](/guides/cloudflare) for more details.
:::

## Minimal Example

Create a basic API token with read-only permissions.
Create a basic API token with read-only permissions for zones.

```ts
import { AccountApiToken } from "alchemy/cloudflare";
Expand All @@ -26,9 +30,64 @@ const token = await AccountApiToken("readonly-token", {
});
```

## R2 Bucket with Pre-Signed URLs

Create an API token for R2 bucket access and use it to generate pre-signed URLs.

```ts
import { AccountApiToken, R2Bucket } from "alchemy/cloudflare";
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

// Create R2 bucket
const bucket = await R2Bucket("my-bucket", {
name: "my-bucket",
});

// Create API token with R2 permissions
const r2Token = await AccountApiToken("r2-access-token", {
name: "R2 Access Token",
policies: [
{
effect: "allow",
permissionGroups: [
"Workers R2 Storage Read",
"Workers R2 Storage Write",
],
resources: {
[`com.cloudflare.edge.r2.bucket.${process.env.CLOUDFLARE_ACCOUNT_ID}_${bucket.jurisdiction ?? "default"}_${bucket.name}`]:
"*",
},
},
],
});

// Configure S3 client with the token
const s3Client = new S3Client({
region: "auto",
endpoint: `https://${process.env.CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: r2Token.accessKeyId.unencrypted,
secretAccessKey: r2Token.secretAccessKey.unencrypted,
},
});

// Generate a pre-signed URL for an object
const command = new GetObjectCommand({
Bucket: bucket.name,
Key: "path/to/file.pdf",
});

const signedUrl = await getSignedUrl(s3Client, command, {
expiresIn: 3600, // URL expires in 1 hour
});

console.log("Pre-signed URL:", signedUrl);
```

## With Time and IP Restrictions

Create a token with time-based and IP address restrictions.
Create a token with time-based and IP address restrictions for enhanced security.

```ts
import { AccountApiToken } from "alchemy/cloudflare";
Expand All @@ -55,19 +114,19 @@ const restrictedToken = await AccountApiToken("restricted-token", {
});
```

## R2 Storage Access Token
## Account-Level Permissions

Create a token with R2 storage write permissions.
Create a token with broad account-level permissions for R2 storage operations.

```ts
import { AccountApiToken } from "alchemy/cloudflare";

const storageToken = await AccountApiToken("account-access-token", {
name: "alchemy-account-access-token",
const accountToken = await AccountApiToken("account-access-token", {
name: "Account R2 Token",
policies: [
{
effect: "allow",
permissionGroups: ["Workers R2 Storage Write"],
permissionGroups: ["Workers R2 Storage Write", "Workers R2 Storage Read"],
resources: {
"com.cloudflare.api.account": "*",
},
Expand All @@ -76,31 +135,24 @@ const storageToken = await AccountApiToken("account-access-token", {
});
```

## Bind to a Worker
## Understanding Access Credentials

Use the token in a Worker binding.
The `AccountApiToken` resource provides S3-compatible credentials through two properties:

```ts
import { Worker, AccountApiToken } from "alchemy/cloudflare";
- **`accessKeyId`**: The token's ID, used as the AWS access key ID
- **`secretAccessKey`**: A SHA-256 hash of the token value, used as the AWS secret access key

These credentials work with any S3-compatible client library, including the AWS SDK.

const token = await AccountApiToken("api-token", {
name: "Worker API Token",
```ts
const token = await AccountApiToken("my-token", {
name: "My Token",
policies: [
{
effect: "allow",
permissionGroups: ["Zone Read"],
resources: {
"com.cloudflare.api.account.zone.*": "*",
},
},
/* ... */
],
});

await Worker("my-worker", {
name: "my-worker",
script: "console.log('Hello, world!')",
bindings: {
API_TOKEN: token,
},
});
// Use with S3 SDK
console.log("Access Key ID:", token.accessKeyId.unencrypted);
console.log("Secret Access Key:", token.secretAccessKey.unencrypted);
```
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Get the account ID from environment variables or API token:
```ts
import { AccountId } from "alchemy/cloudflare";

const accountId = await AccountId("my-account");
const accountId = await AccountId();
```

## With Explicit API Key
Expand All @@ -22,7 +22,7 @@ Provide an API key and email directly:
```ts
import { AccountId } from "alchemy/cloudflare";

const accountId = await AccountId("my-account", {
const accountId = await AccountId(, {
apiKey: alchemy.secret(process.env.CF_API_KEY),
email: "[email protected]",
});
Expand All @@ -35,7 +35,7 @@ Use the account ID with a Worker:
```ts
import { Worker, AccountId } from "alchemy/cloudflare";

const accountId = await AccountId("my-account");
const accountId = await AccountId();

await Worker("my-worker", {
name: "my-worker",
Expand Down
Loading