CarbonFiles Python SDK
Handcrafted Python client for the CarbonFiles file-sharing API. Wraps httpx with a fluent, resource-scoped API featuring upload progress callbacks, multiple source types, and real-time SignalR events.
Installation
pip install carbonfiles-client
For real-time event support via SignalR:
pip install carbonfiles-client[events]
Requires Python 3.10+.
Quick Start
from carbonfiles import CarbonFiles
cf = CarbonFiles("https://files.example.com", "cf4_your_api_key")
# Create a bucket
bucket = cf.buckets.create("my-project", description="Assets", expires="30d")
print(f"Created bucket: {bucket.id}")
# Upload a file
result = cf.buckets[bucket.id].files.upload("/path/to/photo.jpg")
print(f"Uploaded: {result.uploaded[0].name} ({result.uploaded[0].size} bytes)")
# List files
page = cf.buckets[bucket.id].files.list(limit=20)
for f in page.items:
print(f" {f.name} ({f.size} bytes)")
cf.close()
The client also supports context manager usage:
with CarbonFiles("https://files.example.com", "cf4_your_api_key") as cf:
buckets = cf.buckets.list()
Authentication
Pass the token as the second argument when constructing the client:
# API key
cf = CarbonFiles("https://files.example.com", "cf4_your_api_key")
# Admin key
cf = CarbonFiles("https://files.example.com", "your-admin-key")
CarbonFiles supports four token types, all passed as Bearer tokens:
| Type | Format | Scope |
|---|---|---|
| Admin key | Any string | Full access to all operations |
| API key | cf4_ prefix |
Scoped to own buckets |
| Dashboard JWT | JWT token | Admin-level access, 24h max lifetime |
| Upload token | cfu_ prefix |
Scoped to a single bucket, optional rate limit |
Buckets
# Create a bucket
bucket = cf.buckets.create("my-project", description="Assets", expires="30d")
# List buckets
page = cf.buckets.list(limit=20, sort="created_at", order="desc")
# List with expired buckets included
page = cf.buckets.list(include_expired=True)
# Get bucket details
detail = cf.buckets["bucket-id"].get()
# Get bucket details including files
detail = cf.buckets["bucket-id"].get(include_files=True)
# Update a bucket
updated = cf.buckets["bucket-id"].update(name="new-name", description="Updated")
# Delete a bucket
cf.buckets["bucket-id"].delete()
# Get plaintext summary
summary = cf.buckets["bucket-id"].summary()
# Download entire bucket as ZIP
zip_bytes = cf.buckets["bucket-id"].download_zip()
Files
bucket = cf.buckets["bucket-id"]
# List files (paginated)
page = bucket.files.list(limit=50, sort="name", order="asc")
# Tree listing (S3-style delimiter mode)
tree = bucket.files.list_tree(delimiter="/", prefix="docs/")
for d in tree.directories:
print(f" {d.path} ({d.file_count} files, {d.total_size} bytes)")
# Directory listing
listing = bucket.files.list_directory("docs/")
# Upload a file
result = bucket.files.upload("/path/to/file.txt")
# Download a file
data = bucket.files["readme.md"].download()
# Download to a local path
bucket.files["readme.md"].download_to("/tmp/readme.md")
# Get file metadata
meta = bucket.files["readme.md"].metadata()
# Verify file integrity
verify = bucket.files["readme.md"].verify()
print(f"Valid: {verify.valid}")
# Delete a file
bucket.files["old-file.txt"].delete()
# Append data to a file
bucket.files["log.txt"].append(b"new log line\n")
# Patch with byte range
bucket.files["data.bin"].patch(b"\x00" * 100, range_start=0, range_end=99, total_size=1000)
Uploads
From a file path
result = bucket.files.upload("/path/to/photo.jpg")
The filename is derived from the path automatically. Override it if needed:
result = bucket.files.upload("/path/to/photo.jpg", filename="renamed.jpg")
From bytes
result = bucket.files.upload(b"hello world", filename="hello.txt")
From a file-like object (BinaryIO)
with open("report.pdf", "rb") as f:
result = bucket.files.upload(f, filename="report.pdf")
With progress tracking
The progress callback receives (bytes_sent, total_bytes, percentage):
def on_progress(sent: int, total: int | None, pct: float | None):
if pct is not None:
print(f"{pct:.1f}% ({sent}/{total} bytes)")
result = bucket.files.upload("/path/to/large-file.zip", progress=on_progress)
With an upload token
result = bucket.files.upload("/path/to/file.txt", upload_token="cfu_your_upload_token")
Pagination
All list methods return a PaginatedResponse with items, total, limit, and offset fields.
Single page
page = cf.buckets.list(limit=20, offset=0)
print(f"Showing {len(page.items)} of {page.total} buckets")
Auto-pagination
Use list_all() to iterate through all pages automatically:
for page in cf.buckets.list_all(limit=50):
for bucket in page.items:
print(bucket.name)
The same pattern works for files:
for page in cf.buckets["bucket-id"].files.list_all(limit=100):
for f in page.items:
print(f.name)
API Keys (Admin)
# Create an API key
key = cf.keys.create("ci-agent")
print(f"Key: {key.key}") # full key, only shown once
print(f"Prefix: {key.prefix}")
# List API keys
page = cf.keys.list(limit=20)
for k in page.items:
print(f" {k.prefix}: {k.name}")
# Get usage stats for a key
usage = cf.keys["cf4_prefix"].usage()
# Revoke an API key
cf.keys["cf4_prefix"].delete()
Dashboard Tokens (Admin)
# Create a dashboard token
token = cf.dashboard.create_token(expires="24h")
print(f"Token: {token.token}")
# Validate current token
info = cf.dashboard.current_user()
Upload Tokens
Upload tokens are scoped to a single bucket and optionally rate-limited:
# Create an upload token
token = cf.buckets["bucket-id"].tokens.create(expires="1h", max_uploads=10)
print(f"Token: {token.token}")
# Use the token when uploading
cf.buckets["bucket-id"].files.upload("/path/to/file.txt", upload_token=token.token)
Stats (Admin)
stats = cf.stats.get()
print(f"Total buckets: {stats.total_buckets}")
print(f"Total files: {stats.total_files}")
print(f"Total size: {stats.total_size}")
Short URLs
# Delete a short URL
cf.short_urls["abc123"].delete()
Real-Time Events
Real-time events require the events extra:
pip install carbonfiles-client[events]
from carbonfiles.events import CarbonFilesEvents
events = CarbonFilesEvents("https://files.example.com", "cf4_your_api_key")
# Register event handlers
events.on_file_created(lambda data: print(f"File created: {data}"))
events.on_file_deleted(lambda data: print(f"File deleted: {data}"))
events.on_bucket_created(lambda data: print(f"Bucket created: {data}"))
# Connect to the SignalR hub
events.connect()
# Subscribe to events for a specific bucket
events.subscribe_bucket("bucket-id")
# Subscribe to events for a specific file
events.subscribe_file("bucket-id", "path/to/file.txt")
# Subscribe to all events (admin only)
events.subscribe_all()
# Disconnect when done
events.disconnect()
Available events: on_file_created, on_file_updated, on_file_deleted, on_bucket_created, on_bucket_updated, on_bucket_deleted.
Each handler registration returns an unsubscribe callable:
unsubscribe = events.on_file_created(lambda data: print(data))
# Later, remove the handler
unsubscribe()
Error Handling
API errors raise CarbonFilesError with status_code, error, and optional hint:
from carbonfiles import CarbonFiles, CarbonFilesError
cf = CarbonFiles("https://files.example.com", "cf4_your_api_key")
try:
cf.buckets["nonexistent"].get()
except CarbonFilesError as e:
print(f"HTTP {e.status_code}: {e.error}")
if e.hint:
print(f"Hint: {e.hint}")
Async Usage
The AsyncCarbonFiles client provides the same API with async/await:
import asyncio
from carbonfiles import AsyncCarbonFiles
async def main():
async with AsyncCarbonFiles("https://files.example.com", "cf4_your_api_key") as cf:
# Create a bucket
bucket = await cf.buckets.create("my-project", description="Assets")
# Upload a file
result = await cf.buckets[bucket.id].files.upload("/path/to/photo.jpg")
# List files
page = await cf.buckets[bucket.id].files.list(limit=20)
for f in page.items:
print(f" {f.name} ({f.size} bytes)")
# Auto-paginate
async for page in cf.buckets[bucket.id].files.list_all():
for f in page.items:
print(f.name)
# Health check
health = await cf.health()
asyncio.run(main())
License
MIT
Metadata
Release files for carbonfiles-client 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| carbonfiles_client-0.5.0.tar.gz | 19.9 kB | With provenance | Details for carbonfiles_client-0.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| carbonfiles_client-0.5.0-py3-none-any.whl | Python 3 | none | any | Details for carbonfiles_client-0.5.0-py3-none-any.whl |
Total release size: 38.7 kB
Release files / carbonfiles_client-0.5.0.tar.gz
| Download URL | carbonfiles_client-0.5.0.tar.gz |
|---|---|
| Size | 19.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c3120beff416288887bf7e2f85b50054a26ec2313a30bede449e036da9ca0c27
|
|
BLAKE2b-256 checksum How to use checksums |
e25583c9c76c49aeaf655b0f100f86945955dde380916d202b6d39ec20542bcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 20, 2026.
Transparency logRelease files / carbonfiles_client-0.5.0-py3-none-any.whl
| Download URL | carbonfiles_client-0.5.0-py3-none-any.whl |
|---|---|
| Size | 18.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
016d1976ef15ffd465a3e2f444d04608571f04ca5d84718d84413667c014341a
|
|
BLAKE2b-256 checksum How to use checksums |
b4742874134d2878d05ea734c21857878c5feae68a8d74b616eaa3548116739e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 20, 2026.
Transparency logSecurity for carbonfiles-client 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for carbonfiles_client-0.5.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.