Quickstart
Quickstart
from visynx import Visynx
vf = Visynx(api_key="vf_...") # or set VISYNX_API_KEY
model = vf.model("shelf-scanner/3") # your project name and version
result = model.predict("shelf.jpg", confidence=0.4)
for d in result:
print(d.class_name, round(d.confidence, 2), d.box)
result.save("annotated.jpg")
bottle 0.94 [412.0, 118.5, 501.2, 388.0]
bottle 0.91 [502.6, 121.0, 590.4, 390.7]
can 0.78 [604.1, 210.3, 664.9, 372.2]
visynx pulls in only requests and Pillow. No OpenCV, no numpy, no torch —
the models run on Visynx's GPUs, not yours.
Naming a model
Your project and its training version — the same name the app shows you:
model = vf.model(train_name="shelf-scanner", version="3")
model = vf.model("shelf-scanner/3") # the same thing, as one handle
model = vf.model(train_name="shelf-scanner") # newest version
Or take the model with you
Professional and Enterprise accounts can download the weights and run them
themselves. Every plan can keep using hosted predict() instead — downloading
is an option, not a step.
pip install "visynx[local]"
vf = Visynx(api_key="vf_...")
model = vf.model(train_name="shelf-scanner", version="3")
model.download(path="./models/shelf-scanner") # native weights
model.download(path="./models/shelf-scanner", format="onnx") # or a portable export
model.download(path="./models/shelf-scanner", format="edge") # ~4x smaller, for devices
local = vf.load_model("./models/shelf-scanner") # or visynx.load_model(...)
result = local.predict("image.jpg", confidence=0.25)
result.save("annotated.jpg")
| Plan | Hosted predict() |
download() |
Local predict() |
|---|---|---|---|
| Starter | yes | no | no |
| Professional | yes | yes | yes |
| Enterprise | yes | yes | yes |
The check is the server's: an account without the feature gets a
PlanRequiredError and no bytes, whether the call comes from here or from
curl. Downloading someone else's model is refused the same way.
One local call covers every export and every kind of model — detection, instance
segmentation, pose, classification, semantic segmentation, in FP32, FP16 or
Edge. visynx reads what the file is, feeds it the way it expects, and returns
predictions in your image's own pixel coordinates: boxes, outlines, keypoints,
or a blended mask — the same Result the hosted call returns.
local.labels # class names, read from the file
local.runtime # 'portable' or 'native'
local.device # where it is running
Choosing where it runs
Any format — a checkpoint or any of the exports — takes a device:
vf.load_model("./models/x") # "auto": the GPU when there is one
vf.load_model("./models/x", device="cpu") # keep it off the GPU entirely
vf.load_model("./models/x", device="gpu") # insist on the GPU
"gpu" is a requirement rather than a preference, so a machine without one gets
a VisynxError saying what is missing — never a silent fall back to the CPU at
a tenth of the speed. "auto" is the one that falls back, by design.
Portable (.onnx) exports need nothing but visynx[local]. A native checkpoint
also needs the runtime it was trained with; python -m visynx setup installs it.
Run on NVIDIA Jetson
On a Jetson (JetPack 6), a Jetson export loads through TensorRT. The engine is built
on the device the first time the model loads and cached after that: INT8 when the
export ships calibration, FP16 otherwise. TensorRT needs the onnxruntime-gpu build
for JetPack 6 in place of the standard onnxruntime.
Pair the device once. This checks the key and saves it, so Visynx() needs no
arguments on this device:
python -m visynx pair
import visynx
vf = visynx.Visynx() # the paired key
model = vf.model("shelf-scanner/3")
model.download(path="./models/shelf", format="jetson_fp16") # or "jetson_int8"
local = visynx.load_model("./models/shelf")
cam = visynx.open_camera("csi://0") # or "usb://0", or an rtsp:// URL
ok, frame = cam.read()
result = local.predict(frame[..., ::-1]) # OpenCV frames are BGR; predict reads RGB
python -m visynx build-engine ./models/shelf builds the engine ahead of time, so the
first frame is not the slow one. Cameras need OpenCV
(pip install opencv-python-headless). Downloading a model is a Professional and
Enterprise feature; on other plans, hosted predict() works on a Jetson like anywhere
else.
Find your models
for m in vf.models():
print(m.slug, m.display_name)
# shelf-scanner/3 Shelf Scanner v3
# defect-seg/1 Defect Seg v1
"shelf-scanner/3" is the model's slug — your project name and its training
version, the same name you see in the app. A raw "yolo/<job_id>" also works
and skips the lookup.
What you get back
predict() returns a Result: iterate it for detections, or reach for the raw
API payload with .json().
result = model.predict("shelf.jpg")
len(result) # 3
result.detections[0] # Detection('bottle', 0.94)
result.json() # the raw API response, untouched
result.plot() # a PIL image with boxes drawn on
result.save("out.jpg") # ...written to disk
Each Detection carries class_id, class_name, confidence, and box
([x1, y1, x2, y2] in absolute pixels). Segmentation models add polygons;
pose models add keypoints.
Anything image-shaped works
model.predict("shelf.jpg") # a path
model.predict("frames/") # a directory -> list of Results
model.predict(open("shelf.jpg", "rb")) # an open file
model.predict(pil_image) # a PIL image
model.predict(numpy_array) # a numpy array (from OpenCV, say)
Beyond boxes
Two flags the hosted GPUs do for you, with nothing extra to install. Each runs a second model, so each costs extra credits:
# Turn every detected box into a precise instance polygon with SAM 2
result = model.predict("shelf.jpg", segment=True)
result.detections[0].polygons
# Add a monocular depth map, and a relative distance per detection
result = model.predict("shelf.jpg", depth=True)
result.detections[0].depth_median # 0-1, higher is closer
result.depth_image.save("depth.png")
Semantic-segmentation models return a dense mask instead of boxes:
result = model.predict("road.jpg")
result.semantic["legend"] # [{'class_id': 1, 'class_name': 'road', ...}]
result.save("mask.jpg") # the mask, blended over your image
Get an API key
In Visynx, go to Settings → API Keys, create a key, and copy the secret —
it is shown once. Keys start with vf_, never expire, and can be locked to
specific IPs or CIDR ranges. Keep it out of source control:
vf = Visynx() # reads VISYNX_API_KEY
A predict() call spends 1 Vision Credit on the checkpoint or the
full-precision graph, and 2 on the optimised runtimes (format="onnx_fp16" or
format="edge"); format="auto" is billed for whichever it runs. segment=True and depth=True
each add a surcharge for the extra model they run. You are charged only after the
inference succeeds — a failed call is free — and a call retried after a 429 is
billed once, not twice.
Some endpoints are deliberately not reachable with an API key: batch prediction
over a whole dataset, live-camera inference, workflow runs, and the AI-labelling
tools (SAM/DINO/box-prompt). Those run from the Visynx app with a signed-in
session. Calling them with a key returns PermissionDeniedError.
Errors
Every failure is a typed exception, and it quotes the response's X-Request-ID
when the server sent one — include it if you contact support. (Authentication
failures are rejected before that header is assigned, so 401s carry none.)
| Exception | Means | Do |
|---|---|---|
AuthenticationError |
key invalid or revoked | create a new key |
PermissionDeniedError |
email unverified, or the key's IP allowlist rejected you | verify your email / check the allowlist |
InsufficientCreditsError |
out of Vision Credits | top up |
PlanRequiredError |
your plan does not include this (e.g. downloading a model) | upgrade, or use hosted predict() |
ModelNotFoundError |
no such model, or not yours | check vf.models() |
PayloadTooLargeError |
image over 50 MB | resize before sending |
RateLimitError |
rate limited, retries exhausted | back off |
MaintenanceError |
platform in maintenance | retry later |
429s are retried automatically, honouring the server's Retry-After.
All of these subclass VisynxError, so one except VisynxError catches everything.
Self-hosting
Point the client at your own deployment:
vf = Visynx(api_key="vf_...", api_url="https://visynx.internal/api")
or set VISYNX_API_URL.