Overview
Uplint stores every accepted file in your own cloud storage, using credentials you provide. It supports two providers:- Amazon S3 — files are stored as objects in an S3 bucket.
- Azure Blob Storage — files are stored as blobs in an Azure container.
- Google Cloud Storage — files are stored as objects in a GCS bucket (via GCS’s S3-compatible API).
- The provider (
aws_s3,azure_blob, orgcs) - The bucket / container name files are written to
- A base path prefix applied to every object/blob written
- The provider’s credentials (encrypted at rest, never returned)
- A human-friendly name used to identify the bucket in the dashboard and API
All storage bucket endpoints require an API key with the
admin scope. Managing storage is an administrative operation, distinct from the upload/download scopes used for day-to-day file traffic.Choosing a provider
Theprovider field selects the backend. It defaults to aws_s3, so existing S3-only integrations keep working unchanged. Each provider needs its own credential fields:
- Amazon S3 (aws_s3)
- Azure Blob Storage (azure_blob)
- Google Cloud Storage (gcs)
Uplint serves downloads with short-lived S3 pre-signed URLs.
Why multiple buckets?
A single bucket works fine when everything you ingest belongs together. Multiple buckets — even across providers — become useful when different kinds of uploads have different requirements:Data separation
Keep regulated data (e.g. medical claims) in a dedicated bucket, isolated from lower-sensitivity uploads like profile photos.
Data residency
Route EU uploads to an
eu-west-1 S3 bucket and APAC uploads to an Azure container in a nearby region to satisfy residency requirements.Independent credentials
Give each bucket its own IAM key or storage account so you can rotate or revoke access for one workload without touching the others.
Cost & lifecycle
Apply different lifecycle and storage-class/tier policies per bucket, matched to how long each data type must live.
The default bucket
Exactly one bucket is the tenant’s default at any time, regardless of provider. The default is the fallback Uplint uses whenever a more specific bucket can’t be determined — for example, when a file context isn’t bound to a bucket.- The first bucket you add automatically becomes the default.
- Create a bucket with
set_as_default: trueto make it the default on creation. - Promote an existing bucket at any time with the Set Default Bucket endpoint. Promoting one bucket demotes the previous default.
- The default bucket can’t be deleted. Set a different default first.
Routing: which bucket a file goes to
Every file context has an optionalstorage_config_id. That single field decides where a context’s uploads land — the mechanism is identical for both providers.
On upload
When a file is uploaded into a context, Uplint resolves the target bucket in this order:- The context’s
storage_config_id, if it points to an active bucket. - Otherwise — unset, missing, or inactive — the tenant’s default bucket.
On download
Uplint records which bucket each file was written to, so files remain readable even after you add, rename, or re-route buckets. When serving a download it resolves the bucket in this order:- The file’s stored
storage_config_id. - Otherwise, a bucket whose name matches the one recorded on the file (this keeps files uploaded before multi-bucket routing readable).
- Otherwise, the tenant’s default bucket.
Immutable fields
Once a bucket is created, its provider, itsdefault_bucket (the S3 bucket or Azure container name), and its base_path cannot be changed — doing so would orphan every file already stored under them. To move data to a different bucket, container, or prefix, add a new storage bucket and route your contexts to it.
You can always update the safe fields:
Credential handling
Secrets — the AWS secret access key and the Azure account key — are encrypted at rest and are never returned by any endpoint.- S3: when you read a bucket, the
access_key_idcomes back masked (e.g.AKIA...MPLE) so you can recognize which key is in use without exposing it. To change it, submit a newaccess_key_idandsecret_access_key. - Azure: the
account_nameis returned (it isn’t a secret), and theaccount_keyis omitted entirely. To rotate it, submit a newaccount_key.
Deleting a bucket
Deletion is refused when the bucket is either:- the tenant’s default bucket, or
- still bound to one or more file contexts.
Worked example
Register a dedicated bucket for insurance claims, then route a context to it. Pick the tab for your provider.- Amazon S3
- Azure Blob
- Google Cloud Storage
1
Add the S3 bucket
config_id (e.g. cfg_a1b2c3d4e5f6). The access key comes back masked and the secret is omitted.2
Route a context to it
insurance_claims now land in the acme-insurance-claims S3 bucket.3
(Optional) Make it the default
Backward compatibility
Multi-bucket routing and multi-provider support are fully backward compatible. Tenants that already had a single S3 configuration keep working with zero changes: a config with noprovider is treated as aws_s3, its existing config becomes the default bucket, and files uploaded before routing existed continue to resolve by their recorded bucket name. You only opt into more buckets — or into Azure or GCS — when you add one.
API reference
List storage buckets
Every bucket configured for the tenant.
Add a storage bucket
Register a new S3, Azure, or GCS bucket.
Get a storage bucket
Fetch a single bucket by ID.
Update a storage bucket
Rotate credentials, rename, or toggle active.
Set default bucket
Choose the tenant’s fallback bucket.
Delete a storage bucket
Remove an unused bucket.

