Skip to content

Complete Workflow Tutorial

Chain several models into one pipeline: generate a portrait, generate narration, then drive a talking avatar with both.

The key idea is that every task's output is a URL, and those URLs can be passed directly as the next task's input. Nothing needs to be downloaded and re-uploaded in between.

Prerequisites

  • A Get3W account with a paid balance
  • An API key from get3w.com/api-keys
  • Python 3.9+ and requests
bash
pip install requests
export GET3W_API_KEY="sk_your-api-key"

Helpers

Two small helpers cover both call patterns — sync for fast tasks, submit-and-poll for slow ones:

python
import os
import time
import requests

BASE = "https://api.get3w.com/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['GET3W_API_KEY']}",
    "Content-Type": "application/json",
}


def run_sync(slug: str, payload: dict) -> dict:
    """For fast tasks: block until the result comes back."""
    response = requests.post(
        f"{BASE}/{slug}", headers=HEADERS, params={"sync": "true"}, json=payload
    )
    response.raise_for_status()
    return response.json()


def run_async(slug: str, payload: dict, interval: int = 10) -> dict:
    """For slow tasks: submit, then poll until terminal."""
    task = requests.post(f"{BASE}/{slug}", headers=HEADERS, json=payload)
    task.raise_for_status()
    request_id = task.json()["id"]

    while True:
        result = requests.get(
            f"{BASE}/requests/{request_id}", headers=HEADERS
        ).json()
        if result["status"] in ("completed", "failed"):
            return result
        time.sleep(interval)


def first_output(result: dict) -> str:
    if result["status"] != "completed":
        raise RuntimeError(f"Task {result['id']} failed "
                           f"({result.get('code')}): {result.get('error')}")
    return result["outputs"][0]

Step 1: Generate a Portrait

python
image = run_sync("google/nano-banana-pro/text-to-image", {
    "prompt": "Professional headshot of a friendly business woman, "
              "studio lighting, plain white background",
    "aspect_ratio": "1:1",
    "resolution": "1k",
    "output_format": "png",
    "channel": "stable",
})
image_url = first_output(image)

Step 2: Generate Narration

python
speech = run_sync("elevenlabs/eleven-3/text-to-speech", {
    "text": "Hello! Welcome to Get3W. Let me show you how easy it is "
            "to create AI-powered content.",
})
audio_url = first_output(speech)

Step 3: Create the Talking Avatar

Digital human tasks take minutes, so this one goes through run_async:

python
video = run_async("bytedance/omnihuman-1.5/digital-human", {
    "image_url": image_url,
    "audio_url": audio_url,
})
video_url = first_output(video)

Complete Script

python
print("Step 1: generating portrait...")
image_url = first_output(run_sync("google/nano-banana-pro/text-to-image", {
    "prompt": "Professional headshot of a friendly business woman, "
              "studio lighting, plain white background",
    "aspect_ratio": "1:1",
    "resolution": "1k",
    "output_format": "png",
    "channel": "stable",
}))
print(f"  {image_url}")

print("Step 2: generating narration...")
audio_url = first_output(run_sync("elevenlabs/eleven-3/text-to-speech", {
    "text": "Hello! Welcome to Get3W. Let me show you how easy it is "
            "to create AI-powered content.",
}))
print(f"  {audio_url}")

print("Step 3: creating talking avatar (this takes a few minutes)...")
video_url = first_output(run_async("bytedance/omnihuman-1.5/digital-human", {
    "image_url": image_url,
    "audio_url": audio_url,
}))
print(f"  {video_url}")

print("Done.")

Production Notes

  • Use webhooks instead of polling for anything running at scale. Pass ?webhook=<your-url> on submit and handle results as they arrive — see Webhook Mode.
  • Check your balance before long runs. Each task is priced up front and rejected with 402 if the balance won't cover it, so a batch can stop partway through.
  • Download outputs you need to keep. Files stored on Get3W are retained for the current and previous month only.
  • Handle failures per step. A failed task returns HTTP 200 with status: "failed"; the code tells you whether it's worth retrying. Codes 5000, 5003, and 5004 are transient; 1200 and 1401 are not.

Cost

Cost depends on the models, channels, resolution, and duration you pick, and on your account tier's discounts. Image and speech steps are cheap; the digital human step dominates the total. The web interface shows an estimate before you run, and each model's page lists its pricing.

Next Steps

Released under the MIT License.