|
| 1 | +--- |
| 2 | +layout: page |
| 3 | +title: Upload to Backblaze B2 |
| 4 | +nav_title: Backblaze B2 |
| 5 | +permalink: /guides/advanced/storage-destinations/backblaze-b2/ |
| 6 | +parent: Storage Destinations |
| 7 | +grand_parent: Advanced |
| 8 | +great_grand_parent: Guides |
| 9 | +nav_order: 3 |
| 10 | +description: >- |
| 11 | + Upload images generated from HTML/CSS, URL screenshots, and PDFs directly to Backblaze B2 using its S3-compatible API and HTML/CSS to Image. |
| 12 | +--- |
| 13 | + |
| 14 | +# Upload images to Backblaze B2 |
| 15 | +{: .no_toc } |
| 16 | +{: .fs-9 } |
| 17 | + |
| 18 | +Send every rendered image or PDF to a Backblaze B2 bucket you control. |
| 19 | +{: .fs-6 .fw-300 } |
| 20 | + |
| 21 | +<hr> |
| 22 | + |
| 23 | +HTML/CSS to Image connects to Backblaze B2 through its S3-compatible API. A scoped B2 application key supplies the access key ID and secret used by HCTI. |
| 24 | + |
| 25 | +{% include hint.md title="Plan availability" text="Storage destinations are available on the **10,000 images/month plan or higher**. If you'd like to try this on a different plan, email **support@htmlcsstoimage.com**." %} |
| 26 | + |
| 27 | +## Before you begin |
| 28 | + |
| 29 | +You need: |
| 30 | + |
| 31 | +- An existing B2 bucket. |
| 32 | +- The bucket's B2 region, such as `us-west-004`. |
| 33 | +- An optional key prefix, such as `hcti-renders`. |
| 34 | + |
| 35 | +The region appears in the bucket's S3 endpoint: `https://s3.<region>.backblazeb2.com`. |
| 36 | + |
| 37 | +## Create a Backblaze application key |
| 38 | + |
| 39 | +In the Backblaze web console, open **Application Keys** and create a new application key. |
| 40 | + |
| 41 | +1. Give the key a recognizable name. |
| 42 | +2. Restrict it to the destination bucket. |
| 43 | +3. Choose **Read and Write** access if HCTI may need to create later transformations while HCTI Storage is disabled. Write access is enough for base uploads. |
| 44 | +4. If offered, restrict the key to the same file-name prefix you will enter in HCTI. |
| 45 | +5. Copy the resulting `keyID` and `applicationKey`. The application key secret is shown only once. |
| 46 | + |
| 47 | +Do not use the master application key. Backblaze does not support it with the S3-compatible API. |
| 48 | + |
| 49 | +The credentials map to HCTI fields like this: |
| 50 | + |
| 51 | +| Backblaze value | HCTI field | |
| 52 | +|:----------------|:-----------| |
| 53 | +| `keyID` | Access key ID | |
| 54 | +| `applicationKey` | Secret access key | |
| 55 | + |
| 56 | +For least-privilege custom capabilities, `writeFiles` provides uploads, `readFiles` supports later transformations, and `deleteFiles` supports connection-test cleanup. Some S3 integrations also need `listAllBucketNames` for a bucket-scoped key, although HCTI's connection test writes directly to the configured bucket. |
| 57 | + |
| 58 | +## Add Backblaze B2 to HCTI |
| 59 | + |
| 60 | +Open the [Storage Destinations dashboard](https://htmlcsstoimage.com/dashboard/storage-destinations), click **Add storage destination**, and enter: |
| 61 | + |
| 62 | +| HCTI field | Backblaze value | |
| 63 | +|:-----------|:----------------| |
| 64 | +| Provider | **Backblaze B2** | |
| 65 | +| Bucket | Existing B2 bucket name | |
| 66 | +| Key prefix | Optional folder-like prefix, without leading or trailing slashes | |
| 67 | +| Region | Region from the B2 S3 endpoint, such as `us-west-004` | |
| 68 | +| Access key ID | Application key `keyID` | |
| 69 | +| Secret access key | `applicationKey` secret | |
| 70 | + |
| 71 | +Click **Test connection**, then enable and save the destination after the test succeeds. Copy the destination `id` for your API requests. |
| 72 | + |
| 73 | +The test writes a small object under `<key-prefix>/.hcti/connection-tests/`. Cleanup is best-effort, so missing delete access does not make a successful write test fail. |
| 74 | + |
| 75 | +## Upload an HCTI image to B2 |
| 76 | + |
| 77 | +Pass the destination ID as `storage_destination_id` when you create an image: |
| 78 | + |
| 79 | +```bash |
| 80 | +curl -X POST https://hcti.io/v1/image \ |
| 81 | + -u 'user-id:api-key' \ |
| 82 | + -H 'Content-Type: application/json' \ |
| 83 | + -d '{ |
| 84 | + "url": "https://example.com", |
| 85 | + "storage_destination_id": "your-storage-destination-id" |
| 86 | + }' |
| 87 | +``` |
| 88 | + |
| 89 | +Rendering is lazy. With normal HCTI storage enabled, request the returned image URL to render the image and upload the B2 copy. With **Disable HCTI Storage** selected, send an authenticated `PUT` request to the returned `/v1/store/...` URL. |
| 90 | + |
| 91 | +The base object is stored as `<key-prefix>/<image-id>.png`, or `.pdf` when the request uses `pdf_options`. Your B2 bucket settings determine whether that object is private or publicly accessible. |
| 92 | + |
| 93 | +## Troubleshooting Backblaze B2 uploads |
| 94 | + |
| 95 | +- **Authentication fails with a master key** — Create a standard application key; the master application key does not work with the S3-compatible API. |
| 96 | +- **The connection test uses the wrong endpoint** — Enter the region embedded in the bucket's S3 endpoint, including its numeric suffix. |
| 97 | +- **A bucket-scoped key is rejected** — Confirm the key is scoped to the exact bucket. If the error involves listing buckets, enable **Allow List All Bucket Names**. |
| 98 | +- **A later transformation fails with HCTI Storage disabled** — Add `readFiles` access. |
| 99 | +- **Connection-test objects remain** — Add the capabilities Backblaze requires for deleting objects, including `deleteFiles`. |
| 100 | + |
| 101 | +Backblaze documents [creating scoped application keys](https://www.backblaze.com/docs/en/cloud-storage-get-started-with-a-backblaze-integration) and [calling the B2 S3-compatible API](https://www.backblaze.com/docs/en/cloud-storage-call-the-s3-compatible-api). |
| 102 | + |
| 103 | +{% include hint.md title="Next: use your storage destination" text="[Continue to the Storage Destinations guide](/guides/advanced/storage-destinations/) for templates, batches, object storage behavior, and the complete `PUT /v1/store` response." %} |
| 104 | + |
| 105 | +{% include code_footer.md version=1 %} |
0 commit comments