Python SDK
Python SDK
The verbitas package is the official Python client for the Verbitas API.
- PyPI:
verbitas - Python: 3.10+
- License: MIT
Installation
pip install verbitasOr with uv:
uv add verbitasConfiguration
import verbitas
# From environment variable (recommended)client = verbitas.Client() # reads VERBITAS_API_KEY
# Explicit keyclient = verbitas.Client(api_key="vb_live_01j...")
# Custom base URL (e.g. for a self-hosted instance or sandbox)client = verbitas.Client(base_url="https://api.verbitas.io")Set VERBITAS_API_KEY in your environment:
export VERBITAS_API_KEY=vb_live_01j...Signing
Synchronous (small files)
result = client.sign( "output.png", recipe="image-genai-v1", metadata={ "generator": "stable-diffusion-xl", "model": "sdxl-1.0", })
print(result.asset_id) # "a_01j..."print(result.verifier_url) # "https://v.verbitas.io/v/a_01j..."print(result.manifest_uri) # "https://m.verbitas.io/manifests/..."Asynchronous (large files, > ~5 MB)
For large files, client.sign() returns a Job object. Call .wait() to block until complete:
result = client.sign("large_video.mp4", recipe="video-genai-v1")
if result.is_async: result = result.wait(timeout=300) # seconds; raises TimeoutError if exceeded
print(result.asset_id)Sign from bytes or file-like object
import io
with open("output.png", "rb") as f: result = client.sign(f, recipe="image-genai-v1", filename="output.png")image_bytes = generate_image(prompt) # your generation functionresult = client.sign( io.BytesIO(image_bytes), recipe="image-genai-v1", filename="generated.png", metadata={"generator": "my-diffusion-model"})Idempotency key
The SDK generates a UUIDv7 idempotency key automatically for each sign call. To provide your own (for deterministic deduplication):
result = client.sign( "output.png", recipe="image-genai-v1", idempotency_key="01926e7a-f2b3-7abc-8def-0123456789ab")Verifying
# By fileresult = client.verify("received_image.jpg")
# By asset_idresult = client.verify(asset_id="a_01j...")
# By manifest URIresult = client.verify(manifest_uri="https://m.verbitas.io/manifests/a_01j.../manifest.c2pa")
print(result.status) # "verified_manifest_and_watermark_match"print(result.confidence) # 0.97print(result.developer_explanation)print(result.proves) # list of stringsprint(result.does_not_prove) # list of stringsLookup
result = client.lookup("cropped_image.jpg")
for match in result.matches: print(match.asset_id, match.match_type, match.confidence) # a_01j... perceptual_hash 0.81Recipes
# Listrecipes = client.recipes.list()
# Get by IDrecipe = client.recipes.get("image-genai-v1")print(recipe.recipe_yaml)
# Create custom recipe (requires admin key)with open("my-recipe-v1.yaml") as f: result = client.recipes.create(f.read())print(result.recipe_id)Audit log
from datetime import datetime, timezone
entries = client.audit.list( from_dt=datetime(2026, 5, 1, tzinfo=timezone.utc), to_dt=datetime(2026, 5, 9, tzinfo=timezone.utc), event_type="asset.signed",)
for entry in entries: print(entry.timestamp, entry.event_type, entry.data)Webhook event construction
from fastapi import Request
async def webhook_handler(request: Request): payload = await request.body() signature = request.headers.get("Verbitas-Signature")
event = client.webhooks.construct_event( payload=payload, signature=signature, secret="whsec_..." )
if event.type == "job.completed": asset_id = event.data["asset_id"] # update your recordsAsync support
The SDK includes a native async client:
import verbitas.aio
async def sign_image(): async with verbitas.aio.Client() as client: result = await client.sign("output.png", recipe="image-genai-v1") return result.asset_idError handling
from verbitas.exceptions import ( AuthError, QuotaExceededError, RateLimitError, SignerUnavailableError, VerbtiasAPIError,)
try: result = client.sign("image.png", recipe="image-genai-v1")except AuthError as e: print(f"Invalid key: {e.message}")except QuotaExceededError: print("Monthly quota exceeded; upgrade plan")except RateLimitError as e: print(f"Rate limited; retry after {e.retry_after}s")except SignerUnavailableError: # SDK retries automatically (3 attempts); this is raised after all retries fail print("Signer unavailable after retries")except VerbtiasAPIError as e: print(f"API error {e.code}: {e.detail}") print(f"Request ID for support: {e.request_id}")Environment variables
| Variable | Description |
|---|---|
VERBITAS_API_KEY | API key (required unless passed to Client()) |
VERBITAS_BASE_URL | Override base URL (default: https://api.verbitas.io) |
VERBITAS_TIMEOUT | HTTP timeout in seconds (default: 60) |
VERBITAS_MAX_RETRIES | Max retry attempts for 429 and 5xx (default: 3) |