Pixault Documentation Help

Bring Your Own Storage (BYOS)

Pixault can store original images in your own cloud bucket instead of Pixault-managed storage. Transforms, cached variants, metadata, and watermarks remain on Pixault — only originals are externalized.

BYOS is available on Pro (99/mo) plans.

How It Works

Upload → Your Bucket (originals) ↓ Request → Pixault CDN → Pixault API → Fetch from your bucket → Transform → Cache variant (Pixault) → Respond
  • Originals are stored in your S3, Azure Blob, or GCS bucket

  • Pixault reads originals on-demand for transformations

  • Cached variants and metadata stay on Pixault for performance

  • If your bucket is unreachable, Pixault returns an error (no silent fallback)

Supported Providers

Provider

Status

Notes

AWS S3

Supported

Standard S3 regions

S3-compatible (MinIO, Cloudflare R2, Backblaze B2)

Supported

Via custom endpoint

Azure Blob Storage

Supported

Connection string auth

Google Cloud Storage

Supported

Service account JSON key

Configuration

BYOS is configured per project — different projects can use different storage backends.

Prerequisites

  1. An active Pro or Business subscription

  2. A cloud storage bucket with appropriate permissions

  3. Credentials with read/write/delete access to the bucket

Required Bucket Permissions

AWS S3 — your IAM credentials need:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::your-bucket-name/*" } ] }

Azure Blob Storage — the connection string must have read, write, and delete access to the container. A SAS token or storage account key with Blob Service permissions is sufficient.

Google Cloud Storage — the service account needs the Storage Object Admin role (roles/storage.objectAdmin) on the bucket, which grants storage.objects.get, storage.objects.create, and storage.objects.delete.

API Reference

All BYOS endpoints require dashboard authentication (cookie-based). The authenticated user must own the project.

Get Storage Configuration

GET /api/{project}/storage

Returns the current storage configuration for a project. Credentials are never returned.

Response 200 OK

When using Pixault-managed storage (default):

{ "provider": "pixault-managed" }

When BYOS is configured:

{ "provider": "awss3", "bucket": "my-images-bucket", "pathPrefix": "pixault/", "region": "us-east-1", "validated": true, "lastHealthCheck": "2026-03-11T12:00:00Z", "lastHealthCheckResult": "healthy" }

Validate Connection

POST /api/{project}/storage/validate

Test credentials and bucket access without saving. Pixault writes a small sentinel object, reads it back, and deletes it.

Request Body

{ "provider": "s3", "bucket": "my-images-bucket", "pathPrefix": "pixault/", "region": "us-east-1", "accessKeyId": "AKIA...", "secretAccessKey": "wJalr..." }

Response 200 OK

{ "success": true, "error": null }

If validation fails:

{ "success": false, "error": "Access Denied: check that the IAM user has s3:PutObject permission on the bucket." }

Configure BYOS

PUT /api/{project}/storage

Set up BYOS for a project. This endpoint:

  1. Checks your plan allows BYOS

  2. Validates the connection (same as /validate)

  3. Encrypts credentials at rest

  4. Saves the configuration

Request Body (S3)

{ "provider": "s3", "bucket": "my-images-bucket", "pathPrefix": "pixault/", "region": "us-east-1", "accessKeyId": "AKIA...", "secretAccessKey": "wJalr..." }

Request Body (Azure Blob)

{ "provider": "azureblob", "bucket": "my-images-container", "pathPrefix": "pixault/", "connectionString": "DefaultEndpointsProtocol=https;AccountName=..." }

Request Body (Google Cloud Storage)

{ "provider": "gcs", "bucket": "my-images-bucket", "pathPrefix": "pixault/", "serviceAccountJson": "{\"type\": \"service_account\", ...}" }

Request Body (S3-compatible)

For MinIO, Cloudflare R2, Backblaze B2, or other S3-compatible stores, include the endpoint field:

{ "provider": "s3", "bucket": "my-images", "endpoint": "https://your-minio-host:9000", "accessKeyId": "minioadmin", "secretAccessKey": "minioadmin" }

Response 200 OK

{ "configured": true, "provider": "s3" }

Error Responses

Status

Reason

403

Plan does not allow BYOS (upgrade to Pro or Business)

422

Validation failed (credentials invalid, bucket unreachable, permissions insufficient)

Remove BYOS

DELETE /api/{project}/storage

Revert a project to Pixault-managed storage. Existing images in your bucket are not deleted or migrated — they simply won't be accessible through Pixault until you re-configure BYOS or re-upload them.

Response 200 OK

{ "provider": "pixault-managed" }

Health Check

POST /api/{project}/storage/health

Run an on-demand health check against the configured BYOS bucket. Performs the same sentinel write/read/delete cycle as validation.

Response 200 OK

{ "healthy": true, "error": null, "checkedAt": "2026-03-11T12:00:00Z" }

Object Key Format

Pixault stores originals in your bucket using this key structure:

{pathPrefix}{project}/{imageId}

For example, with prefix pixault/ and project myapp:

pixault/myapp/img_01JKXYZ123

If no path prefix is configured, the key is simply {project}/{imageId}.

Security

  • Credentials are encrypted at rest using ASP.NET Core Data Protection

  • Credentials are never returned in API responses

  • Each project's BYOS configuration is independently managed

  • Connection validation runs before credentials are saved

Storage Migration

When you change storage configurations (e.g., enable BYOS, switch between BYOS buckets, or revert to Pixault-managed storage), you can migrate existing originals to the new location.

Start Storage Migration

POST /api/{project}/migrations/storage

Copies all existing originals from the previous store to the current store. During migration, images are served from whichever store has them (dual-read via fallback). No request body required.

Response 202 Accepted

{ "jobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }

How It Works

  1. The previous storage configuration is snapshotted before the migration starts

  2. A fallback store is activated: reads try the new store first, then fall back to the old store

  3. Each image is copied from the old store to the new store (same image ID, metadata untouched)

  4. When complete, the fallback is removed and all reads go to the new store only

This means zero downtime — all image requests succeed throughout the migration.

Bucket Import

If you have pre-existing images in your BYOS bucket (from another service or manual upload), Pixault can discover and index them.

Start Bucket Import

POST /api/{project}/migrations/bucket-import

Scans the BYOS bucket for objects that don't have Pixault metadata and indexes them.

Request Body (optional)

{ "prefixFilter": "photos/" }

Response 202 Accepted

{ "jobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }

What Gets Indexed

  • Objects under the project's key prefix are scanned

  • Objects that already have Pixault metadata are skipped

  • Image dimensions are auto-detected from file headers (first 64KB)

  • If the object key doesn't match Pixault's {project}/{imageId} pattern, a new ID is generated and the object is copied to the correct key

  • Filename, content type, and size are extracted automatically

Monitor Progress

Both storage migration and bucket import jobs use the same status endpoint:

GET /api/{project}/migrations/{jobId}

Returns progress, status, and recent errors. See the Migration API for response format.

Important Notes

  • Storage migration: When you change BYOS configuration, the dashboard prompts you to migrate existing images. Images remain accessible from both stores during migration.

  • Bucket import: Use this to bring pre-existing images under Pixault management. Only images — not videos or arbitrary files — are indexed.

  • Bulk upload from URLs/files: For images scattered across URLs or local storage, use the Upload API or SDKs. The upload API handles any source; no special import tool is needed.

  • No silent fallback: If your bucket is unreachable (network issue, expired credentials, deleted bucket), Pixault returns an error rather than silently falling back to managed storage. This prevents stale or missing images from being served.

  • Cache unaffected: Cached variants already generated from your originals remain in Pixault's cache and continue to be served normally, even if your bucket is temporarily unreachable. Only cache misses requiring the original will fail.

12 March 2026