Back

Blog details

File Management API with FastAPI, Boto3, and AIOZ Storage

AIOZ Network
6 min readAugust 14, 2026
aioz-storage
File Management API with FastAPI, Boto3, and AIOZ Storage

Building a file upload API against AIOZ Storage does not require a special SDK. Boto3, the same AWS SDK used against Amazon S3 itself, works directly, provided you point it at a different endpoint and set one config flag AIOZ's own documentation calls out specifically. This guide builds a working FastAPI Boto3 AIOZ Storage API with upload, list, download, and delete endpoints, and the exact client configuration each one depends on.

TL;DR:

  • Boto3 talks to AIOZ Storage the same way it talks to S3, with a custom endpoint_url and Config(s3={'addressing_style': 'path'}), a setting AIOZ's own SDK docs specify directly.
  • FastAPI's UploadFile streams the request body; boto3's upload_fileobj streams it straight through to AIOZ Storage without buffering the whole file in memory.
  • The full API is four endpoints: upload, list, download, delete, each a thin wrapper around one boto3 S3 client call.

No Special SDK Required: FastAPI and Boto3 Work Directly

FastAPI handles the HTTP layer, boto3 handles the storage calls, and neither one needs an AIOZ-specific replacement. You build against AIOZ Storage's S3-compatible API exactly like you'd build against Amazon S3 itself, since it accepts the same requests. The only AIOZ-specific pieces are the endpoint URL and the access grant credentials you configure the boto3 client with; everything else is standard FastAPI and standard boto3.

Packages and Credentials You Need First

Four Python packages: fastapi, uvicorn (to run it), boto3, and python-multipart, which FastAPI requires internally to parse file uploads even though your code never imports it directly. Install them with pip install fastapi uvicorn boto3 python-multipart.

You also need an AIOZ Storage access grant generated with the "S3 Credentials" type, which returns an Access Key, Secret Key, and endpoint. How access grants work covers what that credential is under the hood; this tutorial just needs the three values it hands back.

Configuring the Boto3 S3 Client for AIOZ Storage

This is the one step where AIOZ Storage genuinely differs from Amazon S3, and AIOZ's own SDK documentation specifies the exact configuration:

import boto3
from botocore.config import Config

s3_client = boto3.client(
    "s3",
    region_name="us-east-1",
    endpoint_url="https://s3.aiozstorage.network",
    aws_access_key_id="<your-aioz-storage-access-key-id>",
    aws_secret_access_key="<your-aioz-storage-secret-access-key>",
    config=Config(s3={"addressing_style": "path"}),
)

Two things matter here beyond the credentials themselves. region_name is required by boto3's client constructor even though AIOZ Storage isn't region-partitioned the way S3 is; AIOZ's own example sets it to us-east-1 as a placeholder value. And addressing_style: "path" is not optional boilerplate, it's specifically what AIOZ's SDK documentation configures, since path-style URLs (endpoint/bucket/key) work against AIOZ's single endpoint in a way that virtual-hosted-style URLs (bucket.endpoint/key) would not.

Building the Upload Endpoint

from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import StreamingResponse

app = FastAPI()
BUCKET = "your-bucket"

@app.post("/files/{filename}")
async def upload_file(filename: str, file: UploadFile = File(...)):
    s3_client.upload_fileobj(file.file, BUCKET, filename)
    return {"filename": filename, "content_type": file.content_type}

file.file is the underlying SpooledTemporaryFile FastAPI's UploadFile wraps around the incoming request body. Passing it directly to upload_fileobj matters: boto3 streams it to AIOZ Storage in chunks rather than reading the entire upload into memory first, which is the difference between this handling a 50MB video file fine and running your server out of memory on a large upload.

Code editor showing a Node.js module with tag and article template functions

Building the List and Download Endpoints

Listing objects in the bucket:

@app.get("/files")
async def list_files():
    response = s3_client.list_objects_v2(Bucket=BUCKET)
    return {"files": [obj["Key"] for obj in response.get("Contents", [])]}

Downloading one back out, streamed rather than loaded fully into memory first:

@app.get("/files/{filename}")
async def download_file(filename: str):
    try:
        obj = s3_client.get_object(Bucket=BUCKET, Key=filename)
    except s3_client.exceptions.NoSuchKey:
        raise HTTPException(status_code=404, detail="File not found")
    return StreamingResponse(
        obj["Body"].iter_chunks(),
        media_type=obj.get("ContentType", "application/octet-stream"),
        headers={"Content-Disposition": f'attachment; filename="{filename}"'},
    )

get_object's Body is a StreamingBody, and iter_chunks() hands FastAPI's StreamingResponse chunks as they arrive from AIOZ Storage instead of waiting for the full object to download server-side first.

Deleting a File

@app.delete("/files/{filename}")
async def delete_file(filename: str):
    s3_client.delete_object(Bucket=BUCKET, Key=filename)
    return {"deleted": filename}

Boto3's delete_object returns a success response even if the key never existed, so this endpoint won't tell you if the filename was wrong, only that the delete call itself completed. If you need to confirm a file existed before deleting it, call head_object first and catch its ClientError the same way the download endpoint catches NoSuchKey.

Running and Testing the API

uvicorn main:app --reload

With the server running, FastAPI's automatic docs at http://localhost:8000/docs let you exercise all four endpoints directly, upload a file, confirm it shows up in the list endpoint, download it back, then delete it, without writing a separate test client. That loop is the fastest way to confirm your access grant credentials and endpoint config are actually correct before wiring this into a real application.

What This Example API Doesn't Handle

Three real gaps worth closing before this touches production traffic. First, none of these endpoints check who's calling them, add a FastAPI dependency that validates an API key or session token before any handler runs. Second, filename comes straight from the URL path and gets used as the S3 key unvalidated, a request for ../../etc/passwd as a filename would get passed through to boto3 as-is, so sanitize it (strip path separators, reject anything outside an allowed character set) before it reaches upload_fileobj or get_object. Third, if a browser calls this API directly rather than another backend service, you'll need CORS middleware, FastAPI's CORSMiddleware handles that, but it's not included here since it depends on which origins you actually want to allow.

Laptop screen showing colorful syntax-highlighted code in a dark editor

Frequently Asked Questions

Do I need a special SDK to use AIOZ Storage with FastAPI?
No. Standard boto3, the same SDK used for Amazon S3, works directly against AIOZ Storage's S3-compatible API once you set a custom endpoint_url and addressing_style: "path".

Why does the boto3 client need region_name if AIOZ Storage isn't region-partitioned?
Boto3's client constructor requires a region value regardless of the target service. AIOZ's own SDK documentation sets it to us-east-1 as a placeholder, since AIOZ Storage doesn't use it the way AWS does.

What does addressing_style: "path" actually do?
It changes how boto3 formats request URLs, from bucket.endpoint/key (virtual-hosted-style) to endpoint/bucket/key (path-style). AIOZ's own SDK documentation configures this setting specifically for its single-endpoint setup.

Why use upload_fileobj and iter_chunks() instead of reading the whole file into memory?
Streaming avoids loading a large upload or download entirely into your API server's memory before passing it along, which matters once files get into the tens or hundreds of megabytes.

What Python packages does this API need?
fastapi, uvicorn, boto3, and python-multipart, the last of which FastAPI needs internally to parse file uploads even though it never appears in your own import statements.

Does delete_object tell me if the file I'm deleting actually existed?
No. It returns success either way. Call head_object first and catch the resulting error if you need to confirm a file exists before deleting it.

Is this example API safe to deploy as-is?
No. It has no request authentication, no filename sanitization against path traversal, and no CORS configuration. Add all three before exposing it beyond local testing.

References

We only send updates when meaningful changes ship, and you can unsubscribe anytime

Related Content

blog thumbnail

What AI Agent Sandboxes on Modal and E2B Actually Store

AI agent sandboxes need external storage for files that outlive the sandbox. Real providers like Modal and E2B mount S3-compatible buckets, AIOZ Storage included.

aioz-storage
6 min readAugust 22, 2026
blog thumbnail

Offloading LangGraph Agent Checkpoints to AIOZ Storage

AIOZ storage can back LangGraph's S3 checkpoint offload tier, but not the whole backend. Here is the real DynamoDB-plus-S3 setup and its credential gap.

aioz-storage
6 min readAugust 21, 2026
blog thumbnail

AIOZ Storage as a Dataset and Model-Output Backend

AIOZ storage for AI datasets means S3-compatible buckets for training data and model outputs, no native versioning or lifecycle policies. Here is the honest scope.

aioz-storage
6 min readAugust 20, 2026
blog thumbnail

AIOZ Storage for AI and Data Pipelines: What's Real

AIOZ storage for AI workloads means S3-compatible object storage for datasets, checkpoints, and model outputs. No vector database. Here is what is real.

aioz-storage
6 min readAugust 19, 2026
blog thumbnail

Managing Team Access and Sub-Users on AIOZ Storage

Add AIOZ storage team members through the dashboard's 3-step wizard: name and password, per-bucket permissions, and a one-time credential download.

aioz-storage
6 min readAugust 18, 2026
blog thumbnail

Calling AIOZ Storage's S3 API Directly with Postman

No Postman collection to import. AIOZ Storage docs show building raw S3 requests by hand, authenticated with AWS Signature and your access grant keys.

aioz-storage
4 min readAugust 17, 2026