Skip to content

About

Python SDK for the Bannerify API: generate images and PDFs from templates

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Bannerify Python SDK

Official Python SDK for Bannerify - Generate images and PDFs at scale via API.

PyPI version Python versions

Installation

pip install bannerify

Or with uv:

uv add bannerify

Quick Start

from bannerify import BannerifyClient

# Create client with your API key
client = BannerifyClient("your-api-key")

# Generate an image
result = client.create_image(
    "tpl_xxxxxxxxx",
    modifications=[
        {"name": "title", "text": "Hello World"},
        {"name": "subtitle", "text": "From Python SDK"}
    ]
)

if "result" in result:
    with open("output.png", "wb") as f:
        f.write(result["result"])
    print("Image created successfully!")
else:
    print(f"Error: {result['error']['message']}")

Features

  • 🚀 Simple, intuitive API
  • 🔒 Type-safe with full type hints
  • ⚡ Built on httpx for performance
  • 🎯 Result/Error pattern for explicit error handling
  • 📝 Comprehensive documentation
  • ✅ Well-tested

Usage

Creating Images

# Generate PNG
result = client.create_image(
    "tpl_xxxxxxxxx",
    modifications=[
        {"name": "title", "text": "My Title"},
        {"name": "image", "src": "https://example.com/image.jpg"}
    ]
)

# Generate WebP
result = client.create_image(
    "tpl_xxxxxxxxx",
    format="webp",
    modifications=[{"name": "title", "text": "My Title"}]
)

Creating PDFs

result = client.create_pdf(
    "tpl_xxxxxxxxx",
    modifications=[{"name": "title", "text": "Invoice #123"}]
)

if "result" in result:
    with open("invoice.pdf", "wb") as f:
        f.write(result["result"])

Generating Signed URLs

signed_url = client.generate_image_signed_url(
    "tpl_xxxxxxxxx",
    modifications=[{"name": "title", "text": "Dynamic Title"}],
    format="png"
)

# Use in HTML
print(f"<img src='{signed_url}' alt='Generated Image' />")

Rendering Videos

A video template renders as an MP4. Each second of the video counts as one generation, and as two at 60 fps.

# Follow the render: created, queued, progress, then done or error
for event in client.render_video("tpl_xxxxxxxxx", modifications=[{"name": "title", "text": "Hi"}]):
    if event["type"] == "progress":
        print(f"{event['progress']:.0%}")
    elif event["type"] == "done":
        print(event["url"])
    elif event["type"] == "error":
        print(event["error"]["message"])

# Or wait for the URL of the MP4
result = client.render_and_wait_video("tpl_xxxxxxxxx")

The created event gives the id of the video. The video renders to its end even when the connection drops. Then render_video reads the same video again by its id: it waits 1, 2, 4 and 8 seconds before each of 4 attempts, and it never sends the render again. When the attempts run out, the last event is an error with the code TIMEOUT_ERROR.

# Start the video and get its id at once, without waiting
created = client.create_video("tpl_xxxxxxxxx")  # {"result": {"id", "status": "queued"}} or {"error": {...}}

create_video sends the render once and never again, because a second request renders a second video.

# Read the video later by its id
video = client.get_video("vid_xxx")  # {"result": {"id", "status", "url"}} or {"error": {...}}

# Follow its events again, from the latest one
for event in client.watch_video("vid_xxx"):
    print(event["type"])

Video Links

A signed URL of a video template plays the video without a request from your server. The video link (m3u8, the default) is an HLS playlist: it starts to play while the video renders, and plays at once when the same video rendered before. An edit renders again only the seconds it changes. mp4 redirects to the MP4 once it rendered, for videos of up to 15 seconds. Video links are for the Scale and Enterprise plans.

video_url = client.generate_video_signed_url(
    "tpl_xxxxxxxxx",
    modifications=[{"name": "title", "text": "Dynamic Title"}],
)

# Safari plays HLS in a <video>; other browsers need an HLS player such as hls.js
print(f"<video src='{video_url}' controls></video>")

mp4_url = client.generate_video_signed_url("tpl_xxxxxxxxx", format="mp4")

Error Handling

result = client.create_image("tpl_xxxxxxxxx")

if "error" in result:
    error = result["error"]
    print(f"Error Code: {error['code']}")
    print(f"Message: {error['message']}")
    print(f"Docs: {error['docs']}")
else:
    # Process result
    image_data = result["result"]

Context Manager

with BannerifyClient("your-api-key") as client:
    result = client.create_image("tpl_xxxxxxxxx")
    # Client is automatically closed

API Reference

BannerifyClient

BannerifyClient(
    api_key: str,
    base_url: str = "https://api.bannerify.co/v1",
    timeout: float = 60.0
)

create_image

client.create_image(
    template_id: str,
    modifications: Optional[List[Dict[str, Any]]] = None,
    format: str = "png"
) -> Dict[str, Any]

create_pdf

client.create_pdf(
    template_id: str,
    modifications: Optional[List[Dict[str, Any]]] = None
) -> Dict[str, Any]

create_stored_image

client.create_stored_image(
    template_id: str,
    modifications: Optional[List[Dict[str, Any]]] = None,
    format: str = "png"
) -> Dict[str, Any]

render_video

client.render_video(
    template_id: str,
    modifications: Optional[List[Dict[str, Any]]] = None
) -> Iterator[Dict[str, Any]]

Yields {"type": "created", "id"}, {"type": "queued", "ahead"}, {"type": "progress", "frame", "totalFrames", "progress"}, then {"type": "done", "url"} or {"type": "error", "error"}.

render_and_wait_video

client.render_and_wait_video(
    template_id: str,
    modifications: Optional[List[Dict[str, Any]]] = None
) -> Dict[str, Any]

watch_video

client.watch_video(video_id: str) -> Iterator[Dict[str, Any]]

Yields the events of render_video again, from the latest one, without created.

create_video

client.create_video(
    template_id: str,
    modifications: Optional[List[Union[Modification, Dict]]] = None
) -> Dict[str, Any]

Starts the video and returns {"result": {"id", "status": "queued"}} or {"error": {...}} at once.

get_video

client.get_video(video_id: str) -> Dict[str, Any]

Returns {"result": {"id", "status", "url"?, "error"?}} or {"error": {...}}. status is queued, rendering, done or failed.

generate_image_signed_url

client.generate_image_signed_url(
    template_id: str,
    modifications: Optional[List[Dict[str, Any]]] = None,
    format: str = "png",
    nocache: bool = False
) -> str

generate_video_signed_url

client.generate_video_signed_url(
    template_id: str,
    modifications: Optional[List[Dict[str, Any]]] = None,
    format: Optional[str] = None,  # "m3u8" (the default) or "mp4"
    nocache: bool = False
) -> str

Examples

Generate Multiple Images

products = [
    {"name": "Product A", "price": "$29.99"},
    {"name": "Product B", "price": "$39.99"},
]

for i, product in enumerate(products):
    result = client.create_image(
        "tpl_product_banner",
        modifications=[
            {"name": "product_name", "text": product["name"]},
            {"name": "price", "text": product["price"]}
        ]
    )
    
    if "result" in result:
        with open(f"banner_{i}.png", "wb") as f:
            f.write(result["result"])

Email Campaigns

for recipient in recipients:
    signed_url = client.generate_image_signed_url(
        "tpl_email_header",
        modifications=[{"name": "name", "text": f"Hi, {recipient['name']}!"}]
    )
    # Use signed_url in email HTML

Development

# Install dependencies
uv sync

# Run tests
uv run pytest

# Type checking
uv run mypy src/

# Format code
uv run ruff format src/

Documentation

Full documentation available at https://bannerify.co/docs/sdk/python/overview

Support

License

MIT License - see LICENSE file for details

About

Python SDK for the Bannerify API: generate images and PDFs from templates

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages