> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reachcrew.space/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloudflare R2

> Create a Cloudflare R2 bucket and API token, connect it to ReachCrew, and store WhatsApp call recordings and contact photos privately.

Cloudflare R2 is the file storage ReachCrew uses for WhatsApp call recordings and contact photos. You need it before you place recorded calls. Without it those two features are off.

> [!NOTE]
>
> **What you need**
>
> * A Cloudflare account with an R2 subscription. Cloudflare bills R2 usage to you directly, with a free allowance each month. Check [R2 pricing](https://developers.cloudflare.com/r2/pricing/) for current terms.
> * The **owner** or **admin** role in ReachCrew.
> * About 10 minutes.

## Overview

ReachCrew stores two kinds of files in your bucket:

* **Call recordings**, under `calls/YYYY/MM/` (one file per call, Opus audio in a `.webm` or `.ogg` container).
* **Contact photos**, under `photos/people/`.

Nothing in the bucket is public. The recorder extension uploads each recording with a **presigned URL** that ReachCrew creates for that one file, and it expires after 15 minutes. Playback in the app uses a presigned link that expires after 5 minutes. Contact photos are shown through a link valid for 1 hour. The Cloudflare key you save never leaves the server.

```mermaid theme={null}
flowchart LR
  E[Recorder extension] -- "presigned PUT, 15 min" --> R[(R2 bucket)]
  A[ReachCrew server] -- "creates presigned URLs" --> E
  B[Browser playback] -- "presigned GET, 5 min" --> R
```

## Connect Cloudflare R2

**1. Create a bucket**

In the [Cloudflare dashboard](https://dash.cloudflare.com), open **Storage & databases → R2 object storage** and create a bucket (see [Cloudflare's guide](https://developers.cloudflare.com/r2/buckets/create-buckets/)). A bucket name uses only lowercase letters, numbers and hyphens, 3 to 63 characters, and does not start or end with a hyphen. Leave it private (the default). If R2 is not enabled yet, Cloudflare asks you to add an R2 subscription first.

**2. Copy your Account ID**

ReachCrew builds the storage address `https://ACCOUNT_ID.r2.cloudflarestorage.com` from it. In the dashboard, press `Cmd/Ctrl + K`, type **Copy account ID** and select the result. Other places are listed in [Cloudflare's guide](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/).

**3. Create an R2 API token**

On the R2 object storage page, click **Manage** next to **API Tokens** (under Account Details). Click **Create Account API token** (or **Create User API token**). Under Permissions choose **Object Read & Write**, and scope the token to the bucket you created. Create it. Cloudflare shows an **Access Key ID** and a **Secret Access Key**. Copy both now: the secret is shown only once. Details are in [Cloudflare's token guide](https://developers.cloudflare.com/r2/api/tokens/).

**4. Open the Integrations page in ReachCrew**

Go to **Settings → WhatsApp → Integrations**. On the **Cloudflare R2** card, click **Connect**.

![The Connect Cloudflare R2 dialog with fields for account ID, bucket name, access key ID and secret access key](https://mintcdn.com/recahcrew/b3LOEBKCy3btecGb/assets/screenshots/app/r2-connect.png?fit=max\&auto=format\&n=b3LOEBKCy3btecGb\&q=85\&s=b2d02e932e6137487196f83be9eced6a)

Four fields, then Connect and test.

**5. Fill in the four fields**

| Field | Where the value is |
| - | - |
| **Account ID** | Step 2. |
| **Bucket name** | The bucket's name exactly as listed under R2 object storage. |
| **Access key ID** | Shown when you created the token in step 3. |
| **Secret access key** | Shown once, next to the access key ID. |

**6. Click Connect & test**

ReachCrew sends one `HeadBucket` request to your bucket with these credentials. If it succeeds, the card shows **Connected**.

> [!NOTE]
>
> You do not need to set up CORS on the bucket. Recordings are uploaded by the recorder extension's background service worker, which has its own host permissions, so the browser does not apply CORS to those requests.

## Check that it works

> [!TIP]
>
> The **Cloudflare R2** card shows **Connected** and a **Last verified** time.

To test end to end, place a short recorded WhatsApp call as described in [Calling](https://docs.reachcrew.space/whatsapp/calling.md). After the call ends, an object appears in your bucket under `calls/`, and the recording plays on the call.

## Troubleshooting

> [accordion] Bucket "name" does not exist
>
> R2 answered 404. Check the **Bucket name** against the list in the Cloudflare dashboard, including hyphens and case.

> [accordion] R2 rejected these credentials for that bucket
>
> R2 answered 401 or 403. The Access Key ID or Secret Access Key is wrong, or the token is not scoped to this bucket, or it lacks **Object Read & Write**. Create a new token and paste both values again.

> [accordion] Could not reach R2 with this account ID
>
> Any other failure. Check the **Account ID** for typos and that your server can reach the internet. If the bucket was created with a jurisdiction (EU, FedRAMP), its endpoint differs from the standard one ReachCrew uses, so use a bucket without a jurisdiction.

> [accordion] Cloudflare R2 is not connected — connect it in Settings → WhatsApp → Integrations
>
> A feature needing R2 (recording, playback, photos) answered 409 because this organization has not connected it. Connect it as above.

> [accordion] storage answered 403
>
> The recorder extension reports `storage answered` followed by R2's status when its upload fails. A 403 usually means the token cannot write to this bucket. Check the token has **Object Read & Write** on it, re-save the credentials, then place a new call.

## Next

> [card] [WhatsApp calling](https://docs.reachcrew.space/whatsapp/calling.md)
>
> Place and record calls.

> [card] [OpenRouter](https://docs.reachcrew.space/integrations/openrouter.md)
>
> Turn on call transcription.

> [card] [Unipile](https://docs.reachcrew.space/integrations/unipile.md)
>
> The connection that links your WhatsApp numbers.

> [card] [Integrations overview](https://docs.reachcrew.space/integrations.md)
>
> All integrations and who can connect them.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.