Skip to main content

Official Python SDK for the FOTOhub AI Platform

Project description

FOTOhub

Official Python SDK for the FOTOhub AI Platform

PyPI Version Python Versions License Downloads Documentation

Generate images, videos, music, and chat with LLMs — all through a single, unified Python client.
Supports 80+ AI models from 10+ providers with built-in credit management.


Features

  • Image Generation — 25+ models including SeedDream 5.0, Flux, SDXL, Midjourney-style, and more
  • Video Generation — Async job-based video creation with polling and image-to-video
  • Music Generation — AI-powered music and audio creation
  • Chat / LLM — OpenAI-compatible chat completions with streaming support
  • Gabriel AI — Intent orchestration engine for natural-language workflows
  • Storage — S3 bucket provisioning with presigned upload/download URLs
  • Translation — Multi-language translation (no auth required)
  • Fully Typed — Complete type annotations with Pydantic v2 models
  • Sync + Async — Both synchronous and asynchronous clients included
  • Automatic Retries — Exponential backoff with configurable retry logic
  • Streaming — Real-time SSE streaming for chat completions

Installation

pip install fotohub

Requires Python 3.9 or higher.

Quick Start

from fotohub import FotoHub

client = FotoHub(api_key="fh_live_...")

# Generate an image
result = client.generate_image(prompt="A mountain landscape at golden hour")
print(result.images[0].url)

Authentication

Get your API key from fotohub.app/settings/api.

from fotohub import FotoHub

# Option 1: Pass directly
client = FotoHub(api_key="fh_live_...")

# Option 2: Environment variable
# export FOTOHUB_API_KEY=fh_live_...
client = FotoHub()

The SDK authenticates via both Authorization: Bearer and x-api-key headers.

Usage Examples

Image Generation

from fotohub import FotoHub

client = FotoHub(api_key="fh_live_...")

# Basic generation (default: SeedDream 5.0 Lite)
result = client.generate_image(
    prompt="A serene Japanese garden with cherry blossoms",
)
print(result.images[0].url)

# Advanced options
result = client.generate_image(
    prompt="Cyberpunk cityscape at night, neon reflections on wet streets",
    model="flux-1-schnell",
    width=1280,
    height=720,
    num_images=2,
    negative_prompt="blurry, low quality",
    seed=42,
    guidance_scale=7.5,
    steps=30,
)

for image in result.images:
    print(f"{image.url}{image.width}x{image.height}, {image.credits_used} credits")

Video Generation

Video generation is asynchronous — submit a job and poll for the result.

from fotohub import FotoHub

client = FotoHub(api_key="fh_live_...")

# Start a video generation job
job = client.generate_video(
    prompt="A drone shot flying over a tropical beach at sunrise",
    duration=5.0,
    aspect_ratio="16:9",
)
print(f"Job started: {job.job_id}")

# Poll until complete (blocks up to 10 minutes)
result = client.poll_video(job.job_id, poll_interval=5.0, max_wait=600)

if result.status == "completed":
    print(f"Video: {result.video_url}")
else:
    print(f"Failed: {result.error}")

Image-to-Video:

job = client.generate_video(
    prompt="Camera slowly zooms in, subtle parallax motion",
    image_url="https://example.com/photo.jpg",
)

Music Generation

from fotohub import FotoHub

client = FotoHub(api_key="fh_live_...")

result = client.generate_music(
    prompt="Upbeat electronic track with heavy bass and synth arpeggios",
    duration=30.0,
)
print(f"Audio: {result.audio.url}")
print(f"Duration: {result.audio.duration}s")
print(f"Credits used: {result.credits_used}")

Chat Completions (OpenAI-Compatible)

from fotohub import FotoHub

client = FotoHub(api_key="fh_live_...")

response = client.chat(
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain quantum computing in simple terms."},
    ],
    model="gpt-4o",
    temperature=0.7,
    max_tokens=1000,
)
print(response.choices[0].message.content)

Streaming Chat

from fotohub import FotoHub

client = FotoHub(api_key="fh_live_...")

stream = client.chat(
    messages=[{"role": "user", "content": "Write a short poem about the sea."}],
    stream=True,
)

for chunk in stream:
    if chunk.delta_content:
        print(chunk.delta_content, end="", flush=True)
print()

# Or collect the entire response at once:
stream = client.chat(messages=[...], stream=True)
full_text = stream.collect()

Gabriel AI (Intent Orchestration)

from fotohub import FotoHub

client = FotoHub()  # No API key needed

result = client.gabriel(
    message="I want to create a logo for my coffee shop",
    context={"user_tier": "pro"},
)
print(f"Intent: {result.intent}")
print(f"Response: {result.response}")
print(f"Suggested actions: {result.actions}")

Storage & S3 Buckets

from fotohub import FotoHub

client = FotoHub(api_key="fh_live_...")

# List buckets
buckets = client.list_buckets()
for bucket in buckets.buckets:
    print(f"{bucket.name} ({bucket.region}) — {bucket.object_count} objects")

# Provision a dedicated S3 bucket
provision = client.provision_s3_bucket(name="my-media-bucket", region="eu-central-1")
print(f"Bucket ID: {provision.bucket_id}")
print(f"Endpoint: {provision.endpoint}")

# Presigned upload
upload = client.presign_upload(
    bucket_id="bucket-123",
    key="images/photo.jpg",
    content_type="image/jpeg",
    expires_in=3600,
)
# Use upload.url with PUT request to upload your file

# Presigned download
download = client.presign_download(bucket_id="bucket-123", key="images/photo.jpg")
print(f"Download: {download.url}")

Translation (No Auth Required)

from fotohub import FotoHub

client = FotoHub()  # No API key needed

result = client.translate(text="Hello, how are you?", target_language="pl")
print(result.translated_text)   # "Cześć, jak się masz?"
print(result.source_language)   # "en"

Usage Analytics

from fotohub import FotoHub

client = FotoHub(api_key="fh_live_...")

usage = client.get_usage(start_date="2026-07-01", end_date="2026-07-18", category="image")
print(f"Total credits: {usage.total_credits_used}")
for record in usage.records:
    print(f"  {record.date}: {record.credits_used} credits ({record.request_count} requests)")

Async Client

Every method is available as an async variant via AsyncFotoHub:

import asyncio
from fotohub import AsyncFotoHub

async def main():
    async with AsyncFotoHub(api_key="fh_live_...") as client:
        # Generate images concurrently
        import asyncio as aio
        results = await aio.gather(
            client.generate_image(prompt="A sunset over mountains"),
            client.generate_image(prompt="A forest in morning mist"),
            client.generate_image(prompt="An ocean wave at golden hour"),
        )
        for r in results:
            print(r.images[0].url)

        # Async streaming chat
        stream = await client.chat(
            messages=[{"role": "user", "content": "Hello!"}],
            stream=True,
        )
        async for chunk in stream:
            if chunk.delta_content:
                print(chunk.delta_content, end="")
        print()

asyncio.run(main())

Error Handling

The SDK raises typed exceptions for all error conditions:

from fotohub import (
    FotoHub,
    AuthError,
    InsufficientCreditsError,
    RateLimitError,
    ValidationError,
    ServerError,
    TimeoutError,
    VideoJobTimeoutError,
)

client = FotoHub(api_key="fh_live_...")

try:
    result = client.generate_image(prompt="test")
except AuthError as e:
    # Invalid or missing API key (HTTP 401/403)
    print(f"Authentication failed: {e}")
except InsufficientCreditsError as e:
    # Not enough credits (HTTP 402)
    print(f"Need credits! Required: {e.credits_required}, Available: {e.credits_available}")
except RateLimitError as e:
    # Too many requests (HTTP 429)
    print(f"Rate limited. Retry after {e.retry_after}s")
except ValidationError as e:
    # Invalid parameters (HTTP 400/422)
    print(f"Invalid request: {e.errors}")
except ServerError as e:
    # Server error (HTTP 5xx)
    print(f"Server error: {e}")
except TimeoutError as e:
    # Request timed out
    print(f"Timed out: {e}")
except VideoJobTimeoutError as e:
    # Video polling exceeded max_wait
    print(f"Video job {e.job_id} timed out")

Exception Hierarchy

Exception HTTP Status Description
FotoHubError Any Base exception for all SDK errors
AuthError 401, 403 Invalid or missing API key
InsufficientCreditsError 402 Account lacks sufficient credits
RateLimitError 429 Rate limit exceeded
ValidationError 400, 422 Invalid request parameters
ServerError 5xx Server-side error
TimeoutError Request timed out or connection failed
VideoJobTimeoutError Video polling exceeded max_wait

All exceptions include status_code and response_body attributes for debugging.

Configuration

from fotohub import FotoHub

client = FotoHub(
    api_key="fh_live_...",
    base_url="https://apis.fotohub.app",  # Custom API endpoint
    timeout=120.0,                         # Request timeout (seconds)
    max_retries=3,                         # Max retry attempts
)

Environment Variables

Variable Description Default
FOTOHUB_API_KEY API key for authentication
FOTOHUB_BASE_URL Override API base URL https://apis.fotohub.app

Retry Behavior

The SDK automatically retries on transient failures:

  • HTTP 429 — Rate limit (respects Retry-After header)
  • HTTP 500, 502, 503, 504 — Server errors
  • Connection timeouts — Network failures

Backoff schedule: 0.5s → 1s → 2s → 4s → ... (capped at 30s).

Context Managers

Both clients support context managers for automatic resource cleanup:

# Sync
with FotoHub(api_key="fh_live_...") as client:
    result = client.generate_image(prompt="test")

# Async
async with AsyncFotoHub(api_key="fh_live_...") as client:
    result = await client.generate_image(prompt="test")

API Reference

FotoHub / AsyncFotoHub

Method Description
generate_image(prompt, *, model, width, height, num_images, ...) Generate images from text
generate_video(prompt, *, model, duration, image_url, aspect_ratio, ...) Start video generation job
poll_video(job_id, *, poll_interval, max_wait) Poll video job until completion
generate_music(prompt, *, model, duration, ...) Generate music from text
chat(messages, *, model, stream, temperature, max_tokens, ...) Chat completion (streaming supported)
translate(text, *, target_language, source_language) Translate text between languages
gabriel(message, *, context) Intent orchestration via Gabriel AI
get_usage(*, start_date, end_date, category) Retrieve usage analytics
list_buckets() List storage buckets
create_bucket(name, *, region) Create a storage bucket
provision_s3_bucket(*, name, region) Provision a dedicated S3 bucket
presign_upload(bucket_id, *, key, content_type, expires_in) Get presigned upload URL
presign_download(bucket_id, *, key, expires_in) Get presigned download URL

Type Safety

The SDK ships with a py.typed marker and full type annotations. All response models are Pydantic v2 BaseModel subclasses:

from fotohub import FotoHub, ImageGenerationResponse, ImageResult

client = FotoHub(api_key="fh_live_...")

result: ImageGenerationResponse = client.generate_image(prompt="test")
image: ImageResult = result.images[0]

# All fields are fully typed
print(image.url)              # str
print(image.width)            # int
print(image.credits_used)     # float
print(image.generation_time_ms)  # Optional[int]

Requirements

Dependency Version
Python >= 3.9
httpx >= 0.24
pydantic >= 2.0

Contributing

We welcome contributions! To get started:

# Clone the repository
git clone https://github.com/fotohubapp/sdk-python.git
cd sdk-python

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
ruff check .

# Run type checking
mypy fotohub/

Please ensure all tests pass and type checks are clean before submitting a pull request.

Links

License

MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fotohub-1.0.0.tar.gz (15.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fotohub-1.0.0-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file fotohub-1.0.0.tar.gz.

File metadata

  • Download URL: fotohub-1.0.0.tar.gz
  • Upload date:
  • Size: 15.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for fotohub-1.0.0.tar.gz
Algorithm Hash digest
SHA256 9aca749745c34219e00a654a44b555784c68ac1a90b151649c6effd67a2865fd
MD5 c2fb7e9889536996efddd85a7af5999d
BLAKE2b-256 7b54f10ac9aebe383b53b2ae69efa1b7e65621457f37c62a3bf78f7c68fd548b

See more details on using hashes here.

File details

Details for the file fotohub-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: fotohub-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for fotohub-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 36ed3ccddce1aace215db97febdc52eda09622fe5dae353004c19571e9c82827
MD5 5b8bf945ec6d20fbe4af633d07291b5e
BLAKE2b-256 261f3e51c93d0c698dfa0c04c4aa35625a9eeeeec4a29e84be660b7605d7ebcf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page