# Wasabi

- Tool: Bubble
- Difficulty: Advanced
- Time required: 2–3 hours
- Last updated: July 2026

## TL;DR

Wasabi is S3-compatible cloud storage at ~$6.99/TB/month with no egress fees and no per-request charges — but it bills a 1 TB minimum per month, so small apps may pay more than with Amazon S3's pay-per-byte model. In Bubble, use the same presigned URL proxy pattern as Amazon S3 but point the AWS SDK at Wasabi's regional endpoint. The endpoint must exactly match your bucket's region — a mismatch causes SignatureDoesNotMatch errors that look like credential problems. Requires a paid Bubble plan for Backend Workflows.

## Bubble + Wasabi: S3-Compatible Storage with No Egress Fees

Wasabi positions itself as 'S3 but cheaper.' The claim holds up for download-heavy applications: while Amazon S3 charges approximately $0.09/GB for egress and additional per-request fees on top of storage, Wasabi charges a single flat rate of approximately $6.99/TB/month with zero egress fees and zero per-request fees. If your Bubble app serves many files to many users, Wasabi's pricing model can be substantially cheaper.

From an integration perspective, Wasabi is an almost perfect S3 drop-in. The API is identical — the same presigned URL pattern that works for Amazon S3 works for Wasabi. The only change is the endpoint URL you configure in the AWS SDK: instead of the default AWS S3 endpoint, you point the SDK at Wasabi's regional endpoint (`s3.us-east-1.wasabisys.com` for US East 1, for example). The Bubble-side integration — API Connector, Backend Workflow, presigned URL flow, browser-side PUT — remains identical.

The endpoint/region matching is the most critical technical detail in the Wasabi integration. Wasabi's regional endpoints are not interchangeable. Each Wasabi bucket lives in a specific region, and the endpoint URL must match that region exactly. Using the generic `s3.wasabisys.com` endpoint only works for `us-east-1` buckets — all other regions require their specific endpoint. Using the wrong endpoint causes `SignatureDoesNotMatch` or `AuthorizationHeaderMalformed` errors that are frustrating to diagnose because they look like credential errors rather than configuration errors.

The 1 TB minimum billing caveat is important to communicate to founders up front. Wasabi bills for a minimum of 1 TB of storage per month even if you store less than 1 TB. At ~$6.99/month minimum, Wasabi costs more than Amazon S3 for small apps storing a few gigabytes (S3 would charge a few cents at that scale). The crossover point where Wasabi becomes cheaper than S3 (factoring in egress) depends on your specific traffic patterns. For apps actively serving files (download-heavy), Wasabi is typically cheaper above approximately 100-200 GB stored. For write-heavy apps or apps storing under 100 GB, S3 or Backblaze B2 may be more cost-effective.

For Bubble specifically: Wasabi does not have native Lambda or CloudFront integrations the way AWS does, but any AWS SDK-compatible library pointed at the Wasabi endpoint works as a presign proxy. The Bubble API Connector, Backend Workflows, privacy rules, and WU considerations are identical to the Amazon S3 pattern. Backend Workflows for the presign call require a paid Bubble plan.

## Before you start

- A Wasabi account at wasabi.com (free to create; billing starts when you create a bucket and store data)
- A Wasabi bucket created in your chosen region — note the exact region code from the Wasabi console
- A Bubble app on a paid plan (Starter or above) — Backend Workflows required for the presign proxy call are not available on the free plan
- An external function deployment environment for the presign proxy: Supabase, AWS Lambda, or Cloudflare Workers
- The Bubble API Connector plugin installed (Plugins tab → Add plugins → search 'API Connector' by Bubble)

## Step-by-step guide

### 1. Create a Wasabi bucket and note the exact regional endpoint

Log into the Wasabi console at console.wasabisys.com. Click 'Create Bucket'. Choose a bucket name (globally unique) and select your target region. Wasabi has multiple regions — choose the region closest to your users or your backend infrastructure.

After creating the bucket, go to its settings or the bucket list — find the S3-compatible endpoint URL for your bucket's region. You will need this exact URL for the presign proxy. Here are the common Wasabi regional endpoints:

- US East 1 (N. Virginia): `s3.us-east-1.wasabisys.com`
- US East 2 (N. Virginia): `s3.us-east-2.wasabisys.com`
- US Central 1 (Texas): `s3.us-central-1.wasabisys.com`
- US West 1 (Oregon): `s3.us-west-1.wasabisys.com`
- EU Central 1 (Amsterdam): `s3.eu-central-1.wasabisys.com`
- EU Central 2 (Frankfurt): `s3.eu-central-2.wasabisys.com`
- AP Northeast 1 (Tokyo): `s3.ap-northeast-1.wasabisys.com`
- AP Northeast 2 (Osaka): `s3.ap-northeast-2.wasabisys.com`

Verify the endpoint directly in the Wasabi console — Wasabi occasionally adds new regions, and the official console always shows the correct endpoint for your specific bucket.

Also configure CORS for the bucket: in the Wasabi console, select your bucket → Properties (or Settings) → CORS. Add a CORS configuration allowing PUT and GET from your Bubble domain:

```json
[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["PUT", "GET"],
    "AllowedOrigins": [
      "https://yourapp.bubbleapps.io",
      "https://www.yourcustomdomain.com"
    ],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3000
  }
]
```

Without CORS, browser-side PUT uploads from Bubble will be blocked by the browser's Same-Origin Policy.

```
[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["PUT", "GET"],
    "AllowedOrigins": [
      "https://yourapp.bubbleapps.io",
      "https://www.yourcustomdomain.com"
    ],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3000
  }
]
```

**Expected result:** Wasabi bucket created in your chosen region. Exact regional endpoint URL noted. CORS configuration saved allowing PUT and GET from your Bubble domain.

### 2. Create a Wasabi access key pair

In the Wasabi console, go to Account (top-right menu) → Access Keys → Create New Access Key. Copy both the Access Key ID and the Secret Access Key immediately — the Secret Access Key is shown only once. Store both values in a secure location (password manager, secrets vault).

Wasabi access keys are equivalent to AWS IAM user access keys. In the presign proxy, you will configure the AWS SDK to use these Wasabi keys with the Wasabi endpoint — the SDK treats them identically to AWS credentials.

You can also create bucket-specific keys in Wasabi for additional security: when creating the key, select 'Sub-User' or apply a bucket policy that restricts the key to operations on your specific bucket only. This limits the blast radius if the key is ever exposed.

Configuration for the presign proxy:
- `AWS_ACCESS_KEY_ID` → Wasabi Access Key ID (starts with `<your-wasabi-key-id>`)
- `AWS_SECRET_ACCESS_KEY` → Wasabi Secret Access Key
- `WASABI_ENDPOINT` → `https://s3.your-region.wasabisys.com` (from Step 1)
- `WASABI_BUCKET` → your bucket name
- `WASABI_REGION` → your region code (e.g., `us-east-1`)

Do not paste these credentials into the Bubble API Connector directly — they go into your proxy function's environment variables (Supabase Secrets, Lambda environment variables, or Cloudflare Worker secrets). The Bubble API Connector only connects to the proxy endpoint, not to Wasabi directly.

**Expected result:** Wasabi Access Key ID and Secret Access Key copied and stored securely. Environment variable names noted for the presign proxy configuration.

### 3. Deploy the presign proxy with Wasabi endpoint configuration

The Wasabi presign proxy is identical to the Amazon S3 presign proxy with one change: the AWS SDK client's endpoint URL is set to your Wasabi regional endpoint instead of the default AWS S3 URL.

Deploy this function as a Supabase Edge Function (or Lambda / Cloudflare Worker):

```javascript
// supabase/functions/wasabi-presign/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { S3Client, PutObjectCommand, GetObjectCommand } from 'npm:@aws-sdk/client-s3';
import { getSignedUrl } from 'npm:@aws-sdk/s3-request-presigner';

const s3 = new S3Client({
  region: Deno.env.get('WASABI_REGION') || 'us-east-1',
  endpoint: Deno.env.get('WASABI_ENDPOINT'),  // e.g. https://s3.us-east-1.wasabisys.com
  credentials: {
    accessKeyId: Deno.env.get('WASABI_ACCESS_KEY_ID') || '',
    secretAccessKey: Deno.env.get('WASABI_SECRET_ACCESS_KEY') || ''
  },
  forcePathStyle: true  // Required for some Wasabi configurations
});

serve(async (req) => {
  const { fileName, contentType, folder = 'uploads', operation = 'put' } = await req.json();

  const key = operation === 'get'
    ? fileName
    : `${folder}/${crypto.randomUUID()}/${fileName}`;

  const command = operation === 'get'
    ? new GetObjectCommand({ Bucket: Deno.env.get('WASABI_BUCKET'), Key: key })
    : new PutObjectCommand({
        Bucket: Deno.env.get('WASABI_BUCKET'),
        Key: key,
        ContentType: contentType
      });

  const url = await getSignedUrl(s3, command, {
    expiresIn: operation === 'get' ? 86400 : 900
  });

  return new Response(JSON.stringify({ url, key }), {
    headers: { 'Content-Type': 'application/json' }
  });
});
```

In Supabase, go to Edge Functions → your function → Secrets. Add:
- `WASABI_ACCESS_KEY_ID` = your Wasabi key ID
- `WASABI_SECRET_ACCESS_KEY` = your Wasabi secret key
- `WASABI_ENDPOINT` = `https://s3.your-region.wasabisys.com`
- `WASABI_BUCKET` = your bucket name
- `WASABI_REGION` = `your-region-code`

Deploy the function with `supabase functions deploy wasabi-presign`. Test it from the command line or Postman with a POST request body `{"fileName": "test.jpg", "contentType": "image/jpeg"}` — you should receive a response with a `url` (Wasabi presigned PUT URL) and `key`.

```
// supabase/functions/wasabi-presign/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { S3Client, PutObjectCommand, GetObjectCommand } from 'npm:@aws-sdk/client-s3';
import { getSignedUrl } from 'npm:@aws-sdk/s3-request-presigner';

const s3 = new S3Client({
  region: Deno.env.get('WASABI_REGION') || 'us-east-1',
  endpoint: Deno.env.get('WASABI_ENDPOINT'),
  credentials: {
    accessKeyId: Deno.env.get('WASABI_ACCESS_KEY_ID') || '',
    secretAccessKey: Deno.env.get('WASABI_SECRET_ACCESS_KEY') || ''
  },
  forcePathStyle: true
});

serve(async (req) => {
  const { fileName, contentType, folder = 'uploads', operation = 'put' } = await req.json();

  const key = operation === 'get'
    ? fileName
    : `${folder}/${crypto.randomUUID()}/${fileName}`;

  const command = operation === 'get'
    ? new GetObjectCommand({ Bucket: Deno.env.get('WASABI_BUCKET'), Key: key })
    : new PutObjectCommand({
        Bucket: Deno.env.get('WASABI_BUCKET'),
        Key: key,
        ContentType: contentType
      });

  const url = await getSignedUrl(s3, command, {
    expiresIn: operation === 'get' ? 86400 : 900
  });

  return new Response(JSON.stringify({ url, key }), {
    headers: { 'Content-Type': 'application/json' }
  });
});
```

**Expected result:** Wasabi presign proxy deployed and callable. POST to the proxy URL returns `{url: 'https://s3.your-region.wasabisys.com/bucket/uploads/uuid/filename?X-Amz-...', key: 'uploads/uuid/filename'}`.

### 4. Configure Bubble API Connector and Backend Workflow

In your Bubble app, go to Plugins tab → install the API Connector by Bubble if not already installed. Click 'API Connector' in the left panel.

Click 'Add another API'. Name it 'Wasabi Presign'. If your proxy requires authentication (e.g., a Supabase Edge Function with Authorization header), add:
- Header: `Authorization`
- Value: `Bearer <your-supabase-anon-key>` (for Supabase Edge Functions) or the function's specific auth mechanism
- Check the **Private** checkbox

Add a call named 'Get Presigned URL':
- Method: POST
- URL: `https://your-project.supabase.co/functions/v1/wasabi-presign` (or your Cloudflare Worker / Lambda URL)
- Body type: JSON
- Body fields: `fileName` (text, dynamic), `contentType` (text, dynamic), `folder` (text, value 'uploads'), `operation` (text, value 'put')

Call configuration:

```json
{
  "method": "POST",
  "url": "https://your-project.supabase.co/functions/v1/wasabi-presign",
  "headers": {
    "Authorization": "Bearer <private>",
    "Content-Type": "application/json"
  },
  "body": {
    "fileName": "<dynamic>",
    "contentType": "<dynamic>",
    "folder": "uploads",
    "operation": "put"
  }
}
```

Set 'Use as' to **Action**. Click **Initialize call**: enter `fileName = test.jpg`, `contentType = image/jpeg`, run. Bubble detects `url` (text) and `key` (text) response fields.

In Backend Workflows, create `Get Wasabi Upload URL` with parameters `file_name` and `content_type`:
1. Call the API Connector action
2. Return data: `presigned_url` = Step 1 url, `object_key` = Step 1 key

Client-side workflow on upload button click:
1. Schedule `Get Wasabi Upload URL` with file details
2. Store returned presigned_url and object_key in App State
3. Run JavaScript (Toolbox plugin): `fetch(presignedUrl, { method: 'PUT', body: file, headers: { 'Content-Type': file.type } })`
4. On success: create WasabiFile Thing with object_key and current user

Add Privacy rules to the WasabiFile data type: only the uploading user can find and read their records.

```
{
  "method": "POST",
  "url": "https://your-project.supabase.co/functions/v1/wasabi-presign",
  "headers": {
    "Authorization": "Bearer <private>",
    "Content-Type": "application/json"
  },
  "body": {
    "fileName": "<dynamic>",
    "contentType": "<dynamic>",
    "folder": "uploads",
    "operation": "put"
  }
}
```

**Expected result:** Bubble API Connector 'Wasabi Presign' group configured with Private auth header. 'Get Presigned URL' call initialized, returning url and key fields. Backend Workflow created and able to return presigned_url and object_key.

### 5. Test uploads and verify Wasabi cost model for your use case

Preview your Bubble app and test the upload flow:
1. Select a file in the File Uploader element
2. Click the upload button to trigger the Backend Workflow
3. Watch Bubble Logs → Workflow logs to confirm the presigned URL is returned
4. Check browser DevTools → Network: a PUT to `s3.your-region.wasabisys.com/...` with a 200 response indicates success
5. Open the Wasabi console → your bucket → Objects to confirm the file appears

**Verify the presigned URL domain**: the URL returned by your proxy should contain `wasabisys.com`, not `amazonaws.com`. If it contains `amazonaws.com`, the proxy's endpoint configuration is not being applied and it is signing for AWS S3 instead of Wasabi.

**Test retrieval**: call the proxy with `operation: 'get'` and the stored object key. The returned presigned GET URL should serve the file correctly when opened in a browser.

**Wasabi cost model check**: before going to production, confirm whether Wasabi's 1 TB minimum makes sense for your app:
- If you expect to store more than ~200 GB with moderate download traffic: Wasabi is likely cheaper than S3
- If you expect to store less than 100 GB: S3 or Backblaze B2 may be cheaper
- If download volume is very low: S3's egress-proportional pricing may cost less than Wasabi's flat minimum

RapidDev's team has built Bubble apps integrating S3-compatible storage providers including Wasabi — if you want help evaluating which storage option fits your expected usage pattern and budget, book a free scoping call at rapidevelopers.com/contact.

**Bubble privacy rules**: confirm your WasabiFile data type has privacy rules so only the uploading user can access their records. Data tab → WasabiFile → Privacy → Add rule.

**Expected result:** File upload to Wasabi works end-to-end: presigned URL from proxy → browser PUT to Wasabi → object key stored in Bubble database → presigned GET URL retrieves the file. Wasabi console shows the uploaded object. Cost model verified for expected usage.

## Best practices

- Always confirm the Wasabi bucket's regional endpoint in the Wasabi console before configuring the proxy — do not assume or guess the endpoint format. Endpoint mismatch is the #1 Wasabi integration failure point.
- Store only the Wasabi object key in Bubble's database, never the presigned URL. Presigned PUT URLs expire in 15 minutes; GET URLs in 24 hours. Always generate fresh presigned GET URLs on demand from the stored key.
- Before choosing Wasabi, calculate whether the 1 TB monthly minimum makes financial sense for your expected storage volume. For apps under ~200 GB with moderate download traffic, Amazon S3 or Backblaze B2 may be cheaper.
- Never add an Authorization header to the browser-side PUT request when uploading to a presigned Wasabi URL. The signature is already baked into the URL query parameters — extra auth headers change the signed payload and cause a 403 SignatureDoesNotMatch error.
- Set Bubble privacy rules on any data type storing Wasabi object keys or file metadata. Without privacy rules, all authenticated Bubble users can query each other's file records even if the Wasabi files themselves are private.
- Configure Wasabi bucket CORS with your specific Bubble app domain rather than a wildcard (*). A wildcard in production allows any website to use stolen presigned URLs to upload to your bucket.
- Use `forcePathStyle: true` in the AWS SDK client config when pointing at Wasabi to ensure compatible URL construction. Some Wasabi regions require path-style URLs; including this option is safe and prevents a category of bucket-not-found errors.
- Rotate Wasabi access keys regularly (every 90 days). Wasabi supports multiple active key pairs simultaneously — create the new key, update the proxy's secrets, verify it works, then delete the old key, all without downtime.

## Use cases

### High-traffic media storage for Bubble apps

For Bubble apps that serve many images or video files to end users — portfolios, media libraries, e-learning platforms — Wasabi's zero egress fee model eliminates one of the largest S3 cost drivers, making it significantly cheaper at scale without changing the integration code.

Prompt example:

```
Build a Bubble media gallery where users upload images via a presigned PUT URL to Wasabi, store the object key in the database, and serve images via presigned GET URLs. At 500 GB stored with heavy download traffic, Wasabi costs roughly the same flat rate while S3 would add significant egress charges.
```

### Document storage for SaaS apps

Store user-generated documents (PDFs, spreadsheets, presentations) in Wasabi from a Bubble SaaS app. The no-per-request-charge model makes Wasabi predictable for apps with variable document access patterns — a busy month with many downloads costs the same as a quiet month.

Prompt example:

```
When a Bubble user uploads a contract PDF, trigger a Backend Workflow that calls the Wasabi presign proxy to get a PUT URL, the browser uploads directly to Wasabi, and the object key is stored in a Documents data type linked to the user's account. Display documents via presigned GET URLs generated on demand.
```

### Backup storage for Bubble app data exports

Schedule regular Bubble Backend Workflows that export data (JSON or CSV) from Bubble's database and store the exports in Wasabi for long-term retention — at a predictable flat storage cost without egress surprises when you need to retrieve backup files.

Prompt example:

```
Create a Bubble Backend Workflow triggered by a recurring schedule that generates a JSON export of key data types, calls the Wasabi presign proxy to get a PUT URL, uploads the export file, and records the Wasabi key and upload timestamp in a Backups data type.
```

## Troubleshooting

### Proxy returns an error or presigned URL upload fails with 403 SignatureDoesNotMatch

Cause: The AWS SDK endpoint in the proxy does not match the Wasabi bucket's actual region. The endpoint must exactly correspond to the region where the bucket was created — for example, a bucket in eu-central-1 requires endpoint `s3.eu-central-1.wasabisys.com`, not `s3.wasabisys.com` or any other variant.

Solution: Check the Wasabi console for the bucket's settings and find the exact S3-compatible endpoint URL listed there. Update the WASABI_ENDPOINT environment variable in your proxy function to match this exact URL. Redeploy the proxy function. Also verify the WASABI_REGION matches the bucket's region code exactly.

### Browser PUT to Wasabi fails with CORS error even though CORS is configured in the bucket

Cause: The CORS configuration in Wasabi does not include the exact origin of your Bubble app, or the AllowedMethods does not include PUT.

Solution: Go to Wasabi console → your bucket → Properties or Settings → CORS. Verify the AllowedOrigins array contains your full Bubble app domain with https:// prefix. Confirm AllowedMethods includes both GET and PUT. If you recently updated the CORS config, wait 1-2 minutes for propagation. Check browser DevTools → Network → preflight OPTIONS request to see what headers Wasabi is returning.

### Upload button does nothing — no Backend Workflow appears in the Bubble Logs tab

Cause: Backend Workflows are only available on paid Bubble plans (Starter and above). On the free plan, scheduling Backend Workflows silently fails without error messages.

Solution: Go to Bubble app Settings → Plan and confirm you are on a paid plan. Upgrade if needed. After upgrading, retry the upload — the Backend Workflow should appear in Logs tab when triggered.

### Initialize call in Bubble API Connector shows 'There was an issue setting up your call'

Cause: The proxy function returned a non-200 response during the initialization test, usually because credentials are missing, the bucket name is wrong, or the proxy is not deployed yet.

Solution: Test the proxy directly: send a POST to your proxy URL with body `{"fileName": "test.jpg", "contentType": "image/jpeg"}` using Postman or curl. Confirm it returns `{url: '...', key: '...'}`. If the proxy returns an error, check the Supabase Edge Function logs (or Lambda CloudWatch logs) for the specific error message. Common issues: missing WASABI_BUCKET env var, wrong endpoint URL, or Wasabi credentials not yet saved to the function's secrets.

### Wasabi billing is unexpectedly high — app stores less than 1 TB but bill shows 1 TB

Cause: Wasabi charges a 1 TB minimum per month regardless of actual storage usage. This is a pricing model characteristic, not an error.

Solution: This is expected Wasabi behavior — 1 TB minimum per month (~$6.99) applies even if you store 1 GB. If your app stores well under 1 TB, consider switching to Amazon S3 (pay-per-byte with no minimum) or Backblaze B2 (10 GB free then ~$6/TB with no minimum). If you plan to grow to over 1 TB with moderate-to-high download traffic, Wasabi's flat rate becomes cost-effective compared to S3 + egress fees.

## Frequently asked questions

### Is the Wasabi integration in Bubble identical to the Amazon S3 integration?

Almost identical. The Bubble API Connector, Backend Workflow, presigned URL flow, and browser-side PUT are exactly the same. The only difference is the proxy function's configuration: the AWS SDK endpoint is set to the Wasabi regional URL instead of the default AWS S3 endpoint, and you use Wasabi access keys instead of IAM access keys. The Bubble side of the integration does not change at all.

### What is the 1 TB minimum billing and how does it affect small apps?

Wasabi charges a minimum of 1 TB of storage per month even if you store less. At ~$6.99/month minimum, Wasabi costs more than Amazon S3 for apps storing only a few gigabytes (S3 would charge a few cents at that scale). The break-even point where Wasabi becomes cheaper than S3 depends on your download volume — Wasabi has no egress fees while S3 charges ~$0.09/GB for egress. If your app actively serves many files to end users, Wasabi typically becomes cost-effective above ~100-200 GB stored.

### Why does my presigned URL contain amazonaws.com instead of wasabisys.com?

The AWS SDK endpoint configuration in your proxy function is not being applied. The SDK is defaulting to the AWS S3 endpoint instead of the Wasabi endpoint. Verify the `endpoint` property is set in the S3Client constructor (see Step 3 code example). Also confirm the WASABI_ENDPOINT environment variable is set correctly in your proxy function's secrets and the function has been redeployed after adding the variable.

### Does Wasabi work with Cloudflare CDN?

Yes. Wasabi participates in the Cloudflare Bandwidth Alliance, which means egress from Wasabi to Cloudflare CDN is free. For download-heavy apps, combining Wasabi storage with Cloudflare CDN can eliminate both S3 egress fees and Cloudflare bandwidth costs. Set up Cloudflare as a CDN layer in front of your Wasabi bucket and serve files through Cloudflare URLs — the presigned URL pattern is used for uploads; Cloudflare handles delivery.

### Can I use Wasabi on Bubble's free plan?

No, not securely. The Backend Workflow required for the presigned URL call is only available on paid Bubble plans (Starter or above). On the free plan, you could technically call the proxy from a client-side workflow, but this exposes your proxy endpoint and any auth credentials to the browser. A paid Bubble plan is required for a secure Wasabi integration.

### How do I serve Wasabi files in Bubble image and video elements?

Store the Wasabi object key in Bubble's database when the upload completes. When you need to display a file, trigger a Backend Workflow that calls your presign proxy with `operation: 'get'` and the stored object key. The proxy returns a presigned GET URL valid for 24 hours. Bind this URL to a Bubble Image or Video element's source field, or to a Link element's URL. Generate a fresh presigned GET URL each time a user needs to view the file — do not store the URL itself in the database.

---

Source: https://www.rapidevelopers.com/bubble-integrations/wasabi
© RapidDev — https://www.rapidevelopers.com/bubble-integrations/wasabi
