Vision
Understand images and video, detect objects, and generate images and video with open models served on the Tenzro Network. Every output names the model, the machine and the node's receipt; generated media also carries a signed manifest.
503 coming_online, and video jobs and runs queue and start by themselves.| Task | Endpoint | Scope |
|---|---|---|
| Describe, read text, answer a question, label | POST /vision/understand | vision:analyse |
| Analyse a video clip (up to 16 frames) | POST /vision/understand | vision:analyse |
| Detect objects | POST /vision/detect | vision:analyse |
| Generate an image | POST /vision/images, POST /v1/images/generations | vision:generate |
| Generate a video (a job) | POST /vision/videos, POST /v1/videos | vision:generate |
| Run a model over an image Dataset | POST /vision/runs | vision:batch |
Understanding
task is describe, read, ask (with question), label (with labels) or analyse_video (with frames, oldest first). Images travel inline as base64 or a data: URI (PNG, JPEG, WebP or GIF, up to 20 MB). A whole clip is not read by the network yet: send frames, or the call answers 503 coming_online.
curl https://api.tenzro.xyz/vision/understand \
-H "Authorization: Bearer $TENZRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"task": "describe", "image": "'"$(base64 < street.jpg)"'"}'Vision describes what an image shows; it never identifies people, and questions that ask who someone is are refused.
Datasets and consent
Generated images and video go into a Dataset with dataset. Inputs are kept only when you ask, with save: say whether people appear, and when they do, give the Fieldwork consent_ref they were collected under. The consent record is re-read at every use; a withdrawn participant's images are never read again. See Fieldwork to collect images and video with consent.
{
"task": "read",
"image": "<base64>",
"save": { "dataset_name": "Receipts", "people": false }
}
# Images that show people are kept only with the Fieldwork consent they were collected under:
"save": { "dataset_id": "ds_…", "people": true, "consent_ref": "fw:<project>:<participant>:<version>" }Image and video generation
Images come back inline with their SHA-256 and a signed manifest in the C2PA assertion model (created by a trained algorithm, the model and its licence, the machine, the node's receipt). Output that cannot be signed is never delivered. The OpenAI SDK works against the /v1 base.
from openai import OpenAI
import base64, os
client = OpenAI(base_url="https://api.tenzro.xyz/v1", api_key=os.environ["TENZRO_API_KEY"])
img = client.images.generate(model="flux2-klein-4b", prompt="A lighthouse at dusk, in ink", size="1024x1024")
open("lighthouse.png", "wb").write(base64.b64decode(img.data[0].b64_json))Video renders as a job. A job whose model is not serving yet stays queued and starts by itself.
curl https://api.tenzro.xyz/vision/videos -H "Authorization: Bearer $TENZRO_API_KEY" -H "Content-Type: application/json" \
-d '{"model": "wan2.2-ti2v-5b", "prompt": "Waves rolling onto a beach at dawn", "seconds": 4, "dataset": {"dataset_name": "Beaches"}}'
# 202 { "id": "vjob_…", "status": "queued", ... }
curl https://api.tenzro.xyz/vision/videos/vjob_… -H "Authorization: Bearer $TENZRO_API_KEY"
curl https://api.tenzro.xyz/vision/videos/vjob_…/content -H "Authorization: Bearer $TENZRO_API_KEY" --output beach.mp4Runs over a Dataset
Describe, detect or label every accepted image of a Dataset, such as a Fieldwork project's. Each result is an item in a new Dataset with its own provenance: the source item, the model, the machine, the receipt and the consent it was collected under.
curl https://api.tenzro.xyz/vision/runs -H "Authorization: Bearer $TENZRO_API_KEY" -H "Content-Type: application/json" \
-d '{"dataset_id": "ds_…", "task": "label", "labels": ["kitchen", "street", "office"]}'SDK and MCP
import { TenzroLabs } from "@tenzrolabs/platform/server";
const tz = new TenzroLabs(); // reads TENZRO_LABS_API_KEY
const { text, provenance } = await tz.vision.describe(await readFile("street.jpg"));
const job = await tz.vision.videos.create({ prompt: "Waves rolling onto a beach at dawn", seconds: 4 });
const done = await tz.vision.videos.wait(job.id);MCP tools: describe_image, read_image_text, ask_about_image, label_image, analyse_video_frames, detect_objects, generate_image, start_video_generation, get_video_generation, start_vision_run, get_vision_run, list_vision_models. See MCP server.
Models and prices
| Model | Task | Licence | Price |
|---|---|---|---|
Qwen 3.8 27B qwen3.8-27b | understand | Apache-2.0 | 200 in / 1200 out per 1M tokens |
Qwen3-VL 8B qwen3-vl-8b | understand | Apache-2.0 | not set yet |
RF-DETR base rf-detr-base | detect | Apache-2.0 | not set yet |
RF-DETR large rf-detr-large | detect | Apache-2.0 | not set yet |
FLUX.2 klein 4B flux2-klein-4b | image | Apache-2.0 | 0 per request |
Z-Image Turbo z-image-turbo | image | Apache-2.0 | not set yet |
Wan 2.2 TI2V 5B wan2.2-ti2v-5b | video | Apache-2.0 | not set yet |
Prices are in Tenzro Labs credits, from the catalogue. A model without a set price is not offered until it has one.
Reference
GET /vision/statusno keyGET /vision/modelsno keyPOST /vision/understandvision:analysePOST /vision/detectvision:analysePOST /vision/imagesvision:generatePOST /vision/videosvision:generateGET /vision/videosvision:generateGET /vision/videos/{id}vision:generateGET /vision/videos/{id}/contentvision:generatePOST /vision/runsvision:batchGET /vision/runsvision:batchGET /vision/runs/{id}vision:batchPOST /vision/runs/{id}/cancelvision:batchGET /vision/outputs/{id}vision:generateGET /vision/outputs/{id}/contentvision:generate