Choose a Vision-capable model
The current public MandAPI pricing metadata marks several enabled models as Vision. Choose an exact model ID available to your account from the current model list. Replace MODEL_ID below with that ID; a text-only model is not a substitute.
This is a compatibility recipe checked against current metadata and local request handling. No real image inference was run for this guide. Object descriptions can be uncertain; they are not guaranteed measurements or a tested detection benchmark.
Save a small request script
Use Python 3.10 or newer and save the following as vision.py. The key stays in your environment. The image is sent as a data URL, so the provider does not need to fetch a public image link.
import argparse
import base64
import json
import mimetypes
import os
from pathlib import Path
import urllib.error
import urllib.request
URL = "https://api.mandapi.com/v1/chat/completions"
def main():
parser = argparse.ArgumentParser()
mode = parser.add_mutually_exclusive_group(required=True)
mode.add_argument("--demo", action="store_true")
mode.add_argument("--live", action="store_true")
parser.add_argument("--model", default="MODEL_ID")
parser.add_argument("--image", type=Path)
parser.add_argument("--language", choices=("en", "es"), default="en")
args = parser.parse_args()
image_url = "data:image/jpeg;base64,IMAGE_BYTES"
if args.live:
key = os.environ.get("MANDAPI_API_KEY")
if not key or args.model == "MODEL_ID" or not args.image:
parser.error("--live needs a private key, a real --model and --image")
mime = mimetypes.guess_type(args.image.name)[0]
if mime not in {"image/jpeg", "image/png", "image/webp"}:
parser.error("Use a JPEG, PNG or WebP image")
image_url = "data:" + mime + ";base64," + base64.b64encode(
args.image.read_bytes()
).decode("ascii")
payload = {
"model": args.model,
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": (
"Enumera los objetos visibles con una descripción breve. "
"Indica la incertidumbre; no deduzcas medidas exactas."
if args.language == "es" else
"List the visible objects and a short description. "
"Say when uncertain. Do not infer exact measurements."
)},
{"type": "image_url", "image_url": {"url": image_url}}
]
}],
"max_tokens": 300
}
if args.demo:
print(json.dumps({"mode": "offline-preview", "request": payload}, indent=2))
return
request = urllib.request.Request(
URL, data=json.dumps(payload).encode("utf-8"),
headers={"Authorization": "Bearer " + key,
"Content-Type": "application/json"}
)
try:
with urllib.request.urlopen(request, timeout=90) as response:
result = json.load(response)
except urllib.error.HTTPError as error:
raise SystemExit("MandAPI HTTP " + str(error.code)) from None
print(result["choices"][0]["message"]["content"])
if __name__ == "__main__":
main()Preview without making a request
python vision.py --demoThis prints the request shape with a placeholder for the image bytes. It does not read a photo or call MandAPI. Pick a small, ordinary JPEG, PNG or WebP for your later live check.
Run with your own image
Set the key privately in the same terminal. In Bash:
read -rsp "MandAPI key: " MANDAPI_API_KEY
printf '\n'
export MANDAPI_API_KEYOr in PowerShell:
$env:MANDAPI_API_KEY = [Net.NetworkCredential]::new('', (Read-Host 'MandAPI key' -AsSecureString)).Passwordpython vision.py --live --image photo.jpg --model MODEL_IDThe explicit --live command sends one chargeable model request. After you run it, compare the answer with the photo and find the corresponding MandAPI usage entry. Keep the API key on your backend if you integrate this into a web app.
Fix common failures
If the model rejects images, recheck its current Vision capability and the exact ID. A valid image extension does not repair corrupt image bytes; open the file locally and re-export it when needed. Check the selected model's image size and format requirements if it rejects a file. If a model rejects max_tokens, use that model's documented output-limit setting rather than inventing another field.
Ask for a list of visible objects or a short description first. Add structured extraction only after checking that the selected model follows your schema; do not promise precise bounding boxes from this example.