On this section
Guide
Getting started with the Python SDK
Install the SDK, submit your first job, and poll it to completion — the submit-and-poll loop every VEED model shares.
Every VEED model works the same way: you submit a job, the API accepts it immediately, and you poll until it is done. This guide walks that loop end to end in Python, using Fabric 1.0 as the example — swap the client attribute and the inputs and the shape is identical for every other model.
Install
The SDK supports Python 3.9 and later.
pip install veedThe client reads VEED_API_KEY from the environment, so export the workspace
key you created in the dashboard:
export VEED_API_KEY="vp_..."The whole loop
from veed import Veed
client = Veed() # reads VEED_API_KEY
job = client.fabric.generate(
audio_url="https://static-assets.veed.io/api-examples/fabric-input.mp3",
image_url="https://static-assets.veed.io/api-examples/fabric-input.png",
resolution="720p",
)
print(job.result)That is the entire integration. generate() submits the job and polls until it
finishes, every 10 seconds
for this model, the interval the API advertises. A rate-limited poll waits for
Retry-After instead, so you do not write a retry loop by hand. Pass
poll_interval= or timeout= to change either.
Construct the client once and reuse it: it is safe to share across threads.
What this model takes
image_urlurlrequiredURL of the source image to animate.
audio_urlurlrequiredURL of the audio track to lip-sync to.
resolutionenumrequiredOutput video resolution.
720p480pEach field is a keyword argument of the same name. Both URLs must be publicly reachable over http(s) — the renderer fetches them itself, so a signed URL is fine but a localhost address is not.
resolution accepts 720p, 480p.
It is required, and the reference and playground both show 720p as
the example, which is the resolution most callers want.
Submitting and polling by hand
If you would rather drive the two calls yourself — a queue worker that persists
the job id across restarts, say — they are the two endpoints generate() wraps:
/v1/fabric-1.0
from veed import Veed
client = Veed() # reads VEED_API_KEY
job = client.fabric.submit(
audio_url="https://static-assets.veed.io/api-examples/fabric-input.mp3",
image_url="https://static-assets.veed.io/api-examples/fabric-input.png",
resolution="720p",
)
print(job.status)/v1/fabric-1.0/{job_id}
from veed import Veed
client = Veed() # reads VEED_API_KEY
job = client.fabric.get("<job_id>")
print(job.status)To resume waiting on a job you submitted earlier, call wait() with its id. It
polls the way generate() does:
job = client.fabric.wait(job_id, timeout=1800)The job envelope is the same either way:
credits_chargedintegeroptionalCredits charged for the job. Present once the job is COMPLETED and the final charge is known.
credits_estimatedintegeroptionalCredits quoted before the job ran. Present only on the response that created the job. This is an estimate, not the price: the charged amount can be higher or lower.
Failure information. Present once the job has FAILED.
Show 3 nested fields
codeenumrequiredStable, machine-readable failure code for this job type.
input_validationcontent_moderationinvalid_fileaudio_too_longtransload_failedgeneration_failedtimeoutinsufficient_creditsOptional structured failure details.
Show 3 nested fields
fieldstringoptionalDotted path to the offending input, when applicable.
messagestringrequiredHuman-readable explanation of this detail.
typestringrequiredThe category of this detail entry.
messagestringrequiredHuman-readable failure message.
job_iduuidrequiredStable identifier of the job and of the resource it produces.
The produced resource. Present once the job is COMPLETED.
Show 1 nested field
Generated lip-synced video.
Show 4 nested fields
content_typestringoptionalThe mime type of the file.
file_namestringoptionalThe name of the file.
file_sizeintegeroptionalThe size of the file in bytes.
urlstringrequiredThe URL where the file can be downloaded from.
statusenumrequiredCurrent lifecycle state of the job.
PROCESSINGCOMPLETEDFAILEDCANCELLEDstatus moves through PROCESSING, COMPLETED, FAILED, CANCELLED. Only
COMPLETED carries a result; only FAILED carries an error.
When a job fails
There are two kinds of failure, and the SDK raises a different exception for each:
- A request the API rejects, before any job exists, raises a subclass of
veed.APIError, withstatus_code,codeandrequest_id. - A job that was accepted but failed while rendering raises
veed.JobFailedErrorfromgenerate()andwait().jobholds the final job, andcodeis one ofinput_validation, content_moderation, invalid_file, audio_too_long, transload_failed, generation_failed, timeout, insufficient_credits.
import veed
try:
job = client.fabric.generate(...)
except veed.JobFailedError as e:
print(e.code, e.message)
except veed.APIError as e:
print(e.status_code, e.code, e.request_id)A cancelled job raises veed.JobCancelledError. If timeout runs out first,
veed.WaitTimeoutError is raised, but the job keeps rendering: call wait()
with its id to pick it up again.
get() raises none of these for a failed job. It returns the job as it is, so
check status yourself, and treat anything other than COMPLETED and
PROCESSING as terminal: a CANCELLED or FAILED job will not change state
again, and polling it further only burns rate limit.
Async
veed.AsyncVeed has the same methods, as coroutines:
import veed
async with veed.AsyncVeed() as client:
job = await client.fabric.generate(...)What it costs
It costs $0.08–$0.15 per second of the generated video, billed on the output rather than on the source image. The pricing page breaks that down per resolution.
Next
- Try the same inputs in the playground before you write any code
- Every other model follows this submit-and-poll shape — the reference pages list the inputs each one takes