---
title: "Create a storage destination"
method: POST
path: "/v1/storage-destinations"
tags: ["Storage Destinations"]
---

# Create a storage destination

`POST /v1/storage-destinations`

## Request

- Base URL: `https://hcti.io`
- URL: `https://hcti.io/v1/storage-destinations`
- Auth: HTTP basic

Tests the connection before saving. Enabled destinations require a successful write test. Explicitly disabled destinations may be saved after a failed test; the response includes the test result. Secret access keys are never returned.

**Rate limit:** 20 requests per minute per organization, shared across all operations in the `storage-destination:write` group and all API keys belonging to that organization.

## Request body

- CreateOrUpdateStorageDestinationRequest: Complete configuration for creating or updating a storage destination. Omitted optional settings are cleared or reset, except a secret explicitly retained using retain_secret_access_key: true. Connection settings are verified before enabling the destination.
  - `name` string, required: Display name for the destination, between 3 and 255 characters.
  - `disabled` boolean: Whether this destination is disabled. Defaults to false. Enabling requires a successful connection test.
  - `hcti_storage_disabled` boolean: Whether to disable HCTI storage for images saved to this destination. When true, rendered files have no public HCTI URL and are not cached by the HCTI CDN. Defaults to false.
  - `connection_info` union, required: Provider-specific storage connection settings.
    - object: Connection settings for Amazon S3.
      - `provider` 'aws_s3', required
      - `region` 'af-south-1' | 'ap-east-1' | 'ap-east-2' | 'ap-northeast-1' | 'ap-northeast-2' | 'ap-northeast-3' | 'ap-south-1' | 'ap-south-2' | 'ap-southeast-1' | 'ap-southeast-2' | 'ap-southeast-3' | 'ap-southeast-4' | 'ap-southeast-5' | 'ap-southeast-6' | 'ap-southeast-7' | 'ca-central-1' | 'ca-west-1' | 'eu-central-1' | 'eu-central-2' | 'eu-north-1' | 'eu-south-1' | 'eu-south-2' | 'eu-west-1' | 'eu-west-2' | 'eu-west-3' | 'il-central-1' | 'me-central-1' | 'me-south-1' | 'mx-central-1' | 'sa-east-1' | 'us-east-1' | 'us-east-2' | 'us-west-1' | 'us-west-2', required
      - `role_arn` string, required: ARN of the IAM role HCTI assumes to access the bucket. Configure its trust policy for this organization before saving.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection settings for Cloudflare R2.
      - `provider` 'cloudflare_r2', required
      - `cloudflare_account_id` string, required: The 32-character hexadecimal Cloudflare account ID that owns the bucket.
      - `cloudflare_jurisdiction` unknown
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `secret_access_key` string, nullable: Secret access key, required on create and when changing provider or access key ID. On update, omitted or null is allowed only with retain_secret_access_key: true and unchanged provider and access key ID. A supplied secret replaces it unless retain_secret_access_key is explicitly true. Up to 990 characters and 996 UTF-8 bytes.
      - `retain_secret_access_key` boolean, nullable: Retain the existing secret access key. Only true retains the secret. Omitted, null, or false requires a supplied secret, including on updates. Explicit true requires existing credentials with unchanged provider and access key ID, and cannot be combined with a supplied secret. False requires a replacement secret, even when disabled.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection settings for Backblaze B2.
      - `provider` 'backblaze_b2', required
      - `region` 'us-west-000' | 'us-west-001' | 'us-west-002' | 'us-west-004' | 'us-east-005' | 'ca-east-006' | 'eu-central-003', required
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `secret_access_key` string, nullable: Secret access key, required on create and when changing provider or access key ID. On update, omitted or null is allowed only with retain_secret_access_key: true and unchanged provider and access key ID. A supplied secret replaces it unless retain_secret_access_key is explicitly true. Up to 990 characters and 996 UTF-8 bytes.
      - `retain_secret_access_key` boolean, nullable: Retain the existing secret access key. Only true retains the secret. Omitted, null, or false requires a supplied secret, including on updates. Explicit true requires existing credentials with unchanged provider and access key ID, and cannot be combined with a supplied secret. False requires a replacement secret, even when disabled.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection settings for DigitalOcean Spaces.
      - `provider` 'digitalocean_spaces', required
      - `region` 'nyc3' | 'ams3' | 'sfo2' | 'sfo3' | 'sgp1' | 'lon1' | 'fra1' | 'tor1' | 'blr1' | 'syd1' | 'atl1' | 'ric1' | 'mkc1', required
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `secret_access_key` string, nullable: Secret access key, required on create and when changing provider or access key ID. On update, omitted or null is allowed only with retain_secret_access_key: true and unchanged provider and access key ID. A supplied secret replaces it unless retain_secret_access_key is explicitly true. Up to 990 characters and 996 UTF-8 bytes.
      - `retain_secret_access_key` boolean, nullable: Retain the existing secret access key. Only true retains the secret. Omitted, null, or false requires a supplied secret, including on updates. Explicit true requires existing credentials with unchanged provider and access key ID, and cannot be combined with a supplied secret. False requires a replacement secret, even when disabled.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection settings for Wasabi.
      - `provider` 'wasabi', required
      - `region` 'us-east-1' | 'us-east-2' | 'us-central-1' | 'us-west-1' | 'us-west-2' | 'ca-central-1' | 'eu-central-1' | 'eu-central-2' | 'eu-west-1' | 'eu-west-2' | 'eu-west-3' | 'eu-south-1' | 'ap-northeast-1' | 'ap-northeast-2' | 'ap-southeast-1' | 'ap-southeast-2', required
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `secret_access_key` string, nullable: Secret access key, required on create and when changing provider or access key ID. On update, omitted or null is allowed only with retain_secret_access_key: true and unchanged provider and access key ID. A supplied secret replaces it unless retain_secret_access_key is explicitly true. Up to 990 characters and 996 UTF-8 bytes.
      - `retain_secret_access_key` boolean, nullable: Retain the existing secret access key. Only true retains the secret. Omitted, null, or false requires a supplied secret, including on updates. Explicit true requires existing credentials with unchanged provider and access key ID, and cannot be combined with a supplied secret. False requires a replacement secret, even when disabled.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection settings for Google Cloud Storage.
      - `provider` 'google_cloud_storage', required
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `secret_access_key` string, nullable: Secret access key, required on create and when changing provider or access key ID. On update, omitted or null is allowed only with retain_secret_access_key: true and unchanged provider and access key ID. A supplied secret replaces it unless retain_secret_access_key is explicitly true. Up to 990 characters and 996 UTF-8 bytes.
      - `retain_secret_access_key` boolean, nullable: Retain the existing secret access key. Only true retains the secret. Omitted, null, or false requires a supplied secret, including on updates. Explicit true requires existing credentials with unchanged provider and access key ID, and cannot be combined with a supplied secret. False requires a replacement secret, even when disabled.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection settings for another S3-compatible provider.
      - `provider` 'other_s3_compatible', required
      - `endpoint` string, required: Public HTTPS endpoint of the S3-compatible service. Do not include a path, query string, fragment, or credentials.
      - `region` string, nullable: Signing region expected by the service. Omit or set to null to use us-east-1.
      - `force_path_style` boolean, nullable: Whether to put the bucket name in the URL path instead of the hostname. Omitted or null defaults to true.
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `secret_access_key` string, nullable: Secret access key, required on create and when changing provider or access key ID. On update, omitted or null is allowed only with retain_secret_access_key: true and unchanged provider and access key ID. A supplied secret replaces it unless retain_secret_access_key is explicitly true. Up to 990 characters and 996 UTF-8 bytes.
      - `retain_secret_access_key` boolean, nullable: Retain the existing secret access key. Only true retains the secret. Omitted, null, or false requires a supplied secret, including on updates. Explicit true requires existing credentials with unchanged provider and access key ID, and cannot be combined with a supplied secret. False requires a replacement secret, even when disabled.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.

## Response `200`

OK

- StorageDestination: A storage destination and the result of its most recent connection test. Secret access keys are never returned.
  - `id` string, required: Storage destination ID.
  - `name` string, required: Display name for the destination.
  - `enabled` boolean: Whether the destination is enabled.
  - `hcti_storage_disabled` boolean: Whether rendered files saved here are excluded from HCTI storage and the HCTI CDN, with no public HCTI image URL.
  - `provider` string: Display name of the storage provider, retained for compatibility. Use connection_info.provider for the provider's machine-readable identifier.
  - `connection_info` union, required: Provider-specific storage connection details. Secret access keys are never returned.
    - object: Connection details for Amazon S3.
      - `provider` 'aws_s3', required
      - `region` 'af-south-1' | 'ap-east-1' | 'ap-east-2' | 'ap-northeast-1' | 'ap-northeast-2' | 'ap-northeast-3' | 'ap-south-1' | 'ap-south-2' | 'ap-southeast-1' | 'ap-southeast-2' | 'ap-southeast-3' | 'ap-southeast-4' | 'ap-southeast-5' | 'ap-southeast-6' | 'ap-southeast-7' | 'ca-central-1' | 'ca-west-1' | 'eu-central-1' | 'eu-central-2' | 'eu-north-1' | 'eu-south-1' | 'eu-south-2' | 'eu-west-1' | 'eu-west-2' | 'eu-west-3' | 'il-central-1' | 'me-central-1' | 'me-south-1' | 'mx-central-1' | 'sa-east-1' | 'us-east-1' | 'us-east-2' | 'us-west-1' | 'us-west-2', required
      - `role_arn` string, required: ARN of the IAM role HCTI assumes to access the bucket. Configure its trust policy for this organization before saving.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection details for Cloudflare R2.
      - `provider` 'cloudflare_r2', required
      - `cloudflare_account_id` string, required: The 32-character hexadecimal Cloudflare account ID that owns the bucket.
      - `cloudflare_jurisdiction` unknown
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection details for Backblaze B2.
      - `provider` 'backblaze_b2', required
      - `region` 'us-west-000' | 'us-west-001' | 'us-west-002' | 'us-west-004' | 'us-east-005' | 'ca-east-006' | 'eu-central-003', required
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection details for DigitalOcean Spaces.
      - `provider` 'digitalocean_spaces', required
      - `region` 'nyc3' | 'ams3' | 'sfo2' | 'sfo3' | 'sgp1' | 'lon1' | 'fra1' | 'tor1' | 'blr1' | 'syd1' | 'atl1' | 'ric1' | 'mkc1', required
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection details for Wasabi.
      - `provider` 'wasabi', required
      - `region` 'us-east-1' | 'us-east-2' | 'us-central-1' | 'us-west-1' | 'us-west-2' | 'ca-central-1' | 'eu-central-1' | 'eu-central-2' | 'eu-west-1' | 'eu-west-2' | 'eu-west-3' | 'eu-south-1' | 'ap-northeast-1' | 'ap-northeast-2' | 'ap-southeast-1' | 'ap-southeast-2', required
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection details for Google Cloud Storage.
      - `provider` 'google_cloud_storage', required
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
    - object: Connection details for another S3-compatible provider.
      - `provider` 'other_s3_compatible', required
      - `endpoint` string, required: Public HTTPS endpoint of the S3-compatible service. Do not include a path, query string, fragment, or credentials.
      - `region` string, nullable: Signing region expected by the service. Omit or set to null to use us-east-1.
      - `force_path_style` boolean, nullable: Whether to put the bucket name in the URL path instead of the hostname. Omitted or null defaults to true.
      - `access_key_id` string, required: S3-compatible access key ID. For Google Cloud Storage, use an HMAC access ID beginning with GOOG.
      - `bucket` string, required: Name of the existing bucket or Space. HCTI does not create it.
      - `key_prefix` string, nullable: Optional prefix for object keys within the bucket. Omitted or null uses the bucket root.
  - `last_tested_at` string, date-time, nullable: UTC timestamp of the most recent connection test, or null if it has not been tested.
  - `last_test_succeeded` boolean, nullable: Whether the most recent write test succeeded, or null if it has not been tested. This does not verify read access or guarantee future availability.
  - `last_test_error` string, nullable: Sanitized error from the most recent failed connection test, or null when no failure is recorded.
  - `created_at` string, date-time: UTC timestamp when the destination was created.
  - `updated_at` string, date-time: UTC timestamp when the destination was last updated.

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `429`: Too Many Requests

## Changes

- **2026-09-14** `d5730c2a58f6`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/htmlcsstoimage/apis/html-css-to-image-api/changes/v1/storage-destinations/post.md)

---

[API](https://skmtc.dev/htmlcsstoimage/apis/html-css-to-image-api.md) - [All operations](https://skmtc.dev/htmlcsstoimage/apis/html-css-to-image-api/llms.txt) - [OpenAPI document](https://skmtc.dev/htmlcsstoimage/apis/html-css-to-image-api/revisions/100550373ae1?raw)
