SDKs
The SDKs wrap the HTTP API: they send your key, retry rate limits, server errors and network failures with backoff, reuse one idempotency key across a create’s retries, poll tasks until they finish and verify webhook signatures. Anything they do, you can also do with plain HTTP; see the API reference.
TypeScript
Section titled “TypeScript”npm install @velvetapi/sdkNo dependencies; runs on Node 18+, Deno, Bun and Cloudflare Workers.
import { VelvetAPI } from "@velvetapi/sdk";
const velvet = new VelvetAPI({ apiKey: process.env.VELVET_API_KEY });
const task = await velvet.tasks.create( { model: "flux-3-klein", user: "user-123", input: { prompt: "A candid photograph of a woman with auburn hair reading on a sunlit balcony, soft morning light, 35mm film grain." }, }, { idempotencyKey: "order-42" },);const done = await velvet.tasks.wait(task.id);console.log(done.state, done.outputs.map((output) => output.url));| Method | Endpoint |
|---|---|
tasks.create({ model, input, user, webhook_url? }, { idempotencyKey? }) |
POST /v1/tasks |
tasks.get(id) |
GET /v1/tasks/{id} |
tasks.list({ limit?, before? }) |
GET /v1/tasks |
tasks.cancel(id) |
POST /v1/tasks/{id}/cancel |
tasks.wait(id, { intervalMs?, timeoutMs? }) |
polls GET /v1/tasks/{id} |
models.list(), models.get(id) |
GET /v1/models, GET /v1/models/{id} |
quotes.create({ model, input }) |
POST /v1/quotes |
account.get() |
GET /v1/account |
reports.create({ category, output_url?, task_id?, email?, details? }) |
POST /v1/reports |
tasks.wait polls every 2 seconds for up to 10 minutes and throws WaitTimeoutError if the task is still running. Error answers throw VelvetAPIError, with status, type, message and the error’s other fields in details.
verifyWebhook checks a delivery’s signature against the raw body and returns the parsed event, or throws WebhookVerificationError:
import { verifyWebhook, WebhookVerificationError } from "@velvetapi/sdk";
try { const event = await verifyWebhook({ body: rawBody, signature: request.headers.get("Velvet-Signature"), secret: process.env.VELVET_WEBHOOK_SECRET! }); if (event.type === "task.succeeded") console.log(event.data.outputs);} catch (err) { if (err instanceof WebhookVerificationError) return new Response("Invalid signature", { status: 400 }); throw err;}Python
Section titled “Python”pip install velvetapiPython 3.9+, with a sync client (VelvetAPI) and an asyncio one (AsyncVelvetAPI) that has the same methods as coroutines.
import os
from velvetapi import VelvetAPI
client = VelvetAPI(api_key=os.environ["VELVET_API_KEY"])
task = client.tasks.create( model="flux-3-klein", user="user-123", input={"prompt": "A candid photograph of a woman with auburn hair reading on a sunlit balcony, soft morning light, 35mm film grain."}, idempotency_key="order-42",)done = client.tasks.wait(task["id"])print(done["state"], [output["url"] for output in done["outputs"]])Responses are plain dictionaries with the same fields as the HTTP API. The methods mirror the TypeScript client with Python names: tasks.get, tasks.list(limit=, before=), tasks.cancel, tasks.wait(task_id, interval=2.0, timeout=600), models.list(), models.get(), quotes.create(model=, input=), account.get() and reports.create(category=, ...). Error answers raise VelvetAPIError.
verify_webhook(body, signature, secret) returns the parsed event or raises WebhookVerificationError:
from velvetapi import WebhookVerificationError, verify_webhook
try: event = verify_webhook(request.get_data(), request.headers.get("Velvet-Signature"), os.environ["VELVET_WEBHOOK_SECRET"])except WebhookVerificationError: abort(400)Without an SDK
Section titled “Without an SDK”Every endpoint takes and returns JSON with a bearer token, so any HTTP client works. Start from the quickstart, and see Tasks and webhooks for signature verification without a library.