Skip to main content

Diffio Python SDK

The Diffio Python SDK helps you call the Diffio API from Python. This version covers project creation, upload, generation, progress checks, and download URLs. Requires Python 3.8 or later.

Install

pip install diffio

For local development:

cd diffio-python
pip install -e .

Configuration

Set the API key with DIFFIO_API_KEY. If you need to set the base URL explicitly, use the production endpoint with DIFFIO_API_BASE_URL.

export DIFFIO_API_KEY="diffio_live_..."
export DIFFIO_API_BASE_URL="https://api.diffio.ai/v1"

Request options

Use request options to override headers, timeouts, retries, or the API key per request. You can also pass timeoutInSeconds as an alias for timeout.

Generation creation is retried only when you supply a non-empty idempotencyKey, even when maxRetries is configured globally or per request. Without a key, a timeout or lost response can hide an accepted generation, so the SDK returns the error after the first attempt. With a key, retries send the same key and payload. Reuse that key when manually retrying the same operation; use a new key for a new generation. The audio isolation and restore helpers do not supply a key and do not automatically retry their generation-creation step.

from diffio import DiffioClient, RequestOptions

client = DiffioClient(apiKey="diffio_live_...")
projects = client.list_projects(
    requestOptions=RequestOptions(
        headers={"X-Debug": "1"},
        timeout=30.0,
        maxRetries=2,
        retryBackoff=0.5,
    )
)

Create a project and generation

create_project uploads the file and returns the project metadata.

from diffio import DiffioClient

client = DiffioClient(apiKey="diffio_live_...")
file_path = "sample.wav"
project = client.create_project(
    filePath=file_path,
)

generation = client.create_generation(
    apiProjectId=project.apiProjectId,
    model="diffio-3.5",
    sampling={"steps": 12, "guidance": 1.5},
    idempotencyKey="restore-job-2026-001",
    requestOptions={"maxRetries": 2},
)

print(generation.generationId)
print(generation.idempotentReplay)

Use one stable idempotencyKey for every retry of the same logical generation request. The response's optional idempotentReplay value is True when the API returns the result of an earlier request with that key. Use a new key for a different generation.

Audio isolation helper

from diffio import DiffioClient

client = DiffioClient(apiKey="diffio_live_...")
result = client.audio_isolation.isolate(
    filePath="sample.wav",
    model="diffio-3.5",
    sampling={"steps": 12, "guidance": 1.5},
)

print(result.generation.generationId)

Restore audio in one call

This helper runs the full flow and returns the downloaded bytes plus a metadata dict.

from diffio import DiffioClient

client = DiffioClient(apiKey="diffio_live_...")
audio_bytes, info = client.restore_audio(
    filePath="sample.wav",
    model="diffio-3.5",
    sampling={"steps": 12, "guidance": 1.5},
    onProgress=lambda progress: print(progress.status),
)

if info["error"]:
    print(info["error"])
else:
    with open("restored.mp3", "wb") as handle:
        handle.write(audio_bytes)

print(info["apiProjectId"], info["generationId"])

Generation progress

wait_for_generation and generations.wait_for_complete wait for the overall status to become complete. Individual stages can reach 100% while video restoration or final settlement is still pending; stage progress alone does not indicate overall completion.

For Diffio 2.0, complete means restored media is ready. Transcription can still be pending, become available later, or finish as unavailable. Read progress.transcription.status independently; progress.transcription is None for older responses that do not report availability. A completed generation remains successful if transcription is unavailable. Completion webhooks expose the same optional event.transcription object; a later transcript does not emit another generation.completed event.

from diffio import DiffioClient

client = DiffioClient(apiKey="diffio_live_...")
progress = client.generations.get_progress(
    generationId="gen_123",
    apiProjectId="proj_123",
)

print(progress.status)
if progress.transcription is not None:
    print(progress.transcription.status)

Generation download

from diffio import DiffioClient

client = DiffioClient(apiKey="diffio_live_...")
download = client.generations.download(
    generationId="gen_123",
    apiProjectId="proj_123",
    downloadType="mp3",
    downloadFilePath="restored.mp3",
)

print(download.downloadUrl)

If you only need the URL, use client.generations.get_download.

Set downloadType="transcript" to download the transcript JSON artifact when the generation has one. Pending transcripts return DiffioApiError with statusCode == 409 and responseBody["code"] == "TRANSCRIPT_PENDING". Unavailable transcripts return statusCode == 404 and responseBody["code"] == "TRANSCRIPT_UNAVAILABLE". These responses include responseBody["transcription"]["status"]. Check the error code to distinguish them from other 409 or 404 errors.

from diffio import DiffioApiError

try:
    transcript = client.generations.download(
        generationId="gen_123",
        apiProjectId="proj_123",
        downloadType="transcript",
        downloadFilePath="word_timestamps.json",
    )
except DiffioApiError as exc:
    body = exc.responseBody if isinstance(exc.responseBody, dict) else {}
    if exc.statusCode == 409 and body.get("code") == "TRANSCRIPT_PENDING":
        print("Transcript is pending; check progress and retry later.")
    elif exc.statusCode == 404 and body.get("code") == "TRANSCRIPT_UNAVAILABLE":
        print("Transcript is unavailable; restored media remains available.")
    else:
        raise

restore_audio(downloadType="transcript") also makes one download request after media completion. It does not wait for a pending transcript. With its default raiseOnError=False, it returns (None, info) and preserves the API error in info["statusCode"] and info["responseBody"]; info["status"] can still be complete because media restoration succeeded. With raiseOnError=True, it raises the same DiffioApiError and attaches the metadata as exc.restoreInfo. Callers can poll progress and retry the transcript download explicitly. Audio and video downloads proceed independently of transcription availability.

Account, keys, usage, and webhook configuration

Agent keys can manage account settings, scoped keys, usage, and webhook endpoints.

settings = client.account.get_settings()
key = client.api_keys.create(
    label="Backend worker",
    scopes=["projects:read", "projects:write", "generations:read", "generations:write", "artifacts:read"],
)
usage = client.usage.summary(apiKeyId=key.keyId)
webhook = client.webhooks.configure(
    mode="live",
    url="https://example.com/webhooks/diffio",
    eventTypes=["generation.completed", "generation.failed"],
    apiKeyId=key.keyId,
)

List projects

from diffio import DiffioClient

client = DiffioClient(apiKey="diffio_live_...")
projects = client.projects.list()

for project in projects.projects:
    print(project.apiProjectId, project.status)

List project generations

from diffio import DiffioClient

client = DiffioClient(apiKey="diffio_live_...")
generations = client.projects.list_generations(apiProjectId="proj_123")

for generation in generations.generations:
    print(generation.generationId, generation.status)

Send a test webhook event

from diffio import DiffioClient

client = DiffioClient(apiKey="diffio_live_...")
event = client.webhooks.send_test_event(
    eventType="generation.completed",
    mode="live",
    samplePayload={"apiProjectId": "proj_123"},
)

print(event.svixMessageId)

Verify webhook signatures

Use the raw request body (bytes) plus the svix-* headers and your webhook signing secret.

from fastapi import FastAPI, Request, HTTPException
from diffio import DiffioClient
import os

app = FastAPI()
client = DiffioClient(apiKey=os.environ["DIFFIO_API_KEY"])

@app.post("/webhooks/diffio")
async def diffio_webhook(request: Request):
    payload = await request.body()
    headers = request.headers
    try:
        event = client.webhooks.verify_signature(
            payload=payload,
            headers=headers,
            secret=os.environ["DIFFIO_WEBHOOK_SECRET"],
        )
    except Exception:
        raise HTTPException(status_code=400, detail="Invalid signature")
    print("Webhook received", event.eventType)
    return {"ok": True}

Tutorials

  • Audio restoration CLI tutorial: tutorials/audio-restoration-cli/README.md

Runtime compatibility

Use Python 3.8 or later.

Tests

cd diffio-python
python -m pip install -r requirements-dev.txt
python -m pytest

Release files for diffio 0.1.86

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for diffio 0.1.86
File Size Uploaded
diffio-0.1.86.tar.gz 31.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for diffio 0.1.86
File Interpreter ABI Platform
diffio-0.1.86-py3-none-any.whl Python 3 none any Details

Total release size: 51.9 kB

Release files / diffio-0.1.86.tar.gz

Download URL diffio-0.1.86.tar.gz
Size 31.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9a8c682d720beec2470dff7993096e226c2ed380f1b97e7a0478e8ade57eaa75
BLAKE2b-256 checksum
How to use checksums
bc255e6f721e22457aee9f2b4871610f74bedc242e6611df8cfc784bbb566982
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 17, 2026.

Transparency log

Release files / diffio-0.1.86-py3-none-any.whl

Download URL diffio-0.1.86-py3-none-any.whl
Size 20.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f69d2b4667daf95fcd7534949d7468ae03c4a7e44e5787106e4aca393d7cc945
BLAKE2b-256 checksum
How to use checksums
584581bd7c3913dc58f26c358288aade8e27b3f375e34a855ba07714f00983a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 17, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.87

2 release files

This release

0.1.86 This release

2 release files

0.1.85

2 release files

0.1.84

2 release files

0.1.83

2 release files

0.1.82

2 release files

0.1.81

2 release files

0.1.80

2 release files

0.1.79

2 release files

0.1.78

2 release files

0.1.77

2 release files

0.1.76

2 release files

0.1.75

2 release files

0.1.74

2 release files

0.1.73

2 release files

0.1.72

2 release files

0.1.71

2 release files

0.1.70

2 release files

0.1.38

2 release files

0.1.37

2 release files

0.1.36

2 release files

0.1.35

2 release files

0.1.34

2 release files

0.1.33

2 release files

0.1.32

2 release files

0.1.31

2 release files

0.1.30

2 release files

0.1.29

2 release files

0.1.28

2 release files

0.1.27

2 release files

0.1.26

2 release files

0.1.25

2 release files

0.1.24

2 release files

0.1.23

2 release files

0.1.22

2 release files

0.1.21

2 release files

0.1.20

2 release files

0.1.19

2 release files

0.1.18

2 release files

0.1.17

2 release files

0.1.16

2 release files

0.1.15

2 release files

0.1.14

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page