Skip to main content

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).
A storage bucket (also called a storage configuration) bundles the details Uplint needs to read and write on your behalf. Some fields are common to both providers; others are provider-specific:
  • The provider (aws_s3, azure_blob, or gcs)
  • 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
A tenant can register many buckets — and they can be a mix of providers. One of them is always the default (fallback) bucket, and each file context can be routed to any active bucket you choose. This lets you keep, say, patient documents in S3 and exports in Azure — each with its own credentials, region, and lifecycle — while still driving everything through one Uplint 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

The provider field selects the backend. It defaults to aws_s3, so existing S3-only integrations keep working unchanged. Each provider needs its own credential fields:
Uplint serves downloads with short-lived S3 pre-signed URLs.
For Azure, the storage account must have “Allow storage account key access” enabled (it is on by default). Without it, Azure rejects the account key and uploads fail with “Key based authentication is not permitted on this storage account.”

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: true to 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 optional storage_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:
  1. The context’s storage_config_id, if it points to an active bucket.
  2. Otherwise — unset, missing, or inactive — the tenant’s default bucket.
Binding a context to a bucket is just setting storage_config_id on the context. Send an empty string when updating a context to unbind it and fall back to the 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:
  1. The file’s stored storage_config_id.
  2. Otherwise, a bucket whose name matches the one recorded on the file (this keeps files uploaded before multi-bucket routing readable).
  3. Otherwise, the tenant’s default bucket.
Because routing is resolved per file, re-pointing a context to a different bucket only affects new uploads. Existing files keep resolving to the bucket — and provider — they were originally written to.

Immutable fields

Once a bucket is created, its provider, its default_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_id comes back masked (e.g. AKIA...MPLE) so you can recognize which key is in use without exposing it. To change it, submit a new access_key_id and secret_access_key.
  • Azure: the account_name is returned (it isn’t a secret), and the account_key is omitted entirely. To rotate it, submit a new account_key.
Use Update Storage Bucket to rotate credentials for either provider.

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.
Reassign or unbind those contexts (and, if needed, promote another bucket to default) before deleting. This guard prevents accidentally cutting off the storage that live contexts depend on.

Worked example

Register a dedicated bucket for insurance claims, then route a context to it. Pick the tab for your provider.
1

Add the S3 bucket

The response returns a config_id (e.g. cfg_a1b2c3d4e5f6). The access key comes back masked and the secret is omitted.
2

Route a context to it

New uploads into 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 no provider 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.