Genjutsu 1.0 API
Find Genjutsu 1.0 model IDs, request examples, and current availability on ModelPort.
Call GET /v1/models with your key and check available before submitting.
Request parameters
| Parameter | Accepted values | Default |
|---|---|---|
resolution | 480p, 720p, 1080p | 720p |
aspect_ratio | auto | auto |
generate_audio | false | false |
n | 1 | 1 |
Reference files
| Input mode | Roles and allowed counts |
|---|---|
| reference | reference_image (1–10), reference_video (1–1) |
Upload a 1–30 second MP4 and one to ten reference images. Output follows the source duration. Omit duration and read the billed seconds from pricing.quantity. The minimum is four seconds.
Quote and submit
Set MODELPORT_API_KEY. The cURL example uses Bash and jq, Python uses its standard library, and Node.js uses a .mjs file. These examples submit a job after retrieving a quote.
Upload the required files and set MODELPORT_REFERENCE_IMAGE_ID, MODELPORT_REFERENCE_VIDEO_ID.
cURL (Bash)
cURL (Bash)
set -eu
: "${MODELPORT_API_KEY:?Set MODELPORT_API_KEY}"
base='https://api.apimodel.store'
request='{"model":"genjutsu-1.0","prompt":"A low camera moves along a misty river.","parameters":{"resolution":"720p","aspect_ratio":"auto","generate_audio":false,"n":1},"references":[{"role":"reference_image","file_id":"REPLACE_WITH_UPLOADED_FILE_ID"},{"role":"reference_video","file_id":"REPLACE_WITH_UPLOADED_FILE_ID"}]}'
request=$(printf '%s' "$request" | jq -ce --arg role 'reference_image' --arg id "${MODELPORT_REFERENCE_IMAGE_ID:?Set MODELPORT_REFERENCE_IMAGE_ID}" '(.references[] | select(.role == $role) | .file_id) = $id')
request=$(printf '%s' "$request" | jq -ce --arg role 'reference_video' --arg id "${MODELPORT_REFERENCE_VIDEO_ID:?Set MODELPORT_REFERENCE_VIDEO_ID}" '(.references[] | select(.role == $role) | .file_id) = $id')
request_id=${MODELPORT_REQUEST_ID:-modelport-example-$(date +%s)-$$}
quote=$(curl --fail-with-body --max-time 45 -sS 'https://api.apimodel.store/v1/quotes' \
-H "Authorization: Bearer $MODELPORT_API_KEY" \
-H "Content-Type: application/json" --data "$request")
quoted_cap=$(printf '%s' "$quote" | jq -er '.billing_price_usd | strings')
cap=${MODELPORT_MAX_PRICE_USD:-$quoted_cap}
printf 'Request ID: %s, maximum charge: %s USD\n' "$request_id" "$cap" >&2
payload=$(printf '%s' "$request" | jq -ce --arg cap "$cap" '. + {max_price_usd: $cap}')
job=$(curl --fail-with-body --max-time 45 -sS "$base/v1/jobs" \
-H "Authorization: Bearer $MODELPORT_API_KEY" -H "Idempotency-Key: $request_id" \
-H "Content-Type: application/json" --data "$payload")
job_id=$(printf '%s' "$job" | jq -er '.id | strings')
printf 'Job ID: %s\n' "$job_id" >&2
attempt=0
while [ "$attempt" -lt 90 ]; do
status=$(printf '%s' "$job" | jq -er '.status')
case "$status" in succeeded|failed) break ;; esac
sleep 2
job=$(curl --fail-with-body --max-time 45 -sS "$base/v1/jobs/$job_id" -H "Authorization: Bearer $MODELPORT_API_KEY")
attempt=$((attempt + 1))
done
printf '%s\n' "$job"Python
Python
import json
import os
import time
import uuid
from urllib.request import Request, urlopen
BASE = "https://api.apimodel.store"
KEY = os.environ["MODELPORT_API_KEY"]
request_id = os.getenv("MODELPORT_REQUEST_ID") or str(uuid.uuid4())
payload = json.loads("{\"model\":\"genjutsu-1.0\",\"prompt\":\"A low camera moves along a misty river.\",\"parameters\":{\"resolution\":\"720p\",\"aspect_ratio\":\"auto\",\"generate_audio\":false,\"n\":1},\"references\":[{\"role\":\"reference_image\",\"file_id\":\"REPLACE_WITH_UPLOADED_FILE_ID\"},{\"role\":\"reference_video\",\"file_id\":\"REPLACE_WITH_UPLOADED_FILE_ID\"}]}")
for reference in payload["references"]:
reference["file_id"] = os.environ[f'MODELPORT_{reference["role"].upper()}_ID']
def api(path, data=None, request_key=None):
headers = {"Authorization": f"Bearer {KEY}"}
if data is not None:
headers["Content-Type"] = "application/json"
if request_key:
headers["Idempotency-Key"] = request_key
body = json.dumps(data).encode("utf-8") if data is not None else None
with urlopen(Request(BASE + path, data=body, headers=headers), timeout=45) as response:
return json.load(response)
quote = api("/v1/quotes", payload)
cap = os.getenv("MODELPORT_MAX_PRICE_USD") or quote["billing_price_usd"]
print(f"Request ID: {request_id}, maximum charge: {cap} USD", flush=True)
job = api("/v1/jobs", {**payload, "max_price_usd": cap}, request_id)
job_id = job["id"]
print("Job ID:", job_id, flush=True)
for _ in range(90):
if job["status"] in ("succeeded", "failed"):
break
time.sleep(2)
job = api(f"/v1/jobs/{job_id}")
print(json.dumps(job, indent=2, ensure_ascii=False))Node.js
Node.js
import { randomUUID } from "node:crypto";
import { setTimeout as sleep } from "node:timers/promises";
const base = "https://api.apimodel.store";
const key = process.env.MODELPORT_API_KEY;
if (!key) throw new Error("Set MODELPORT_API_KEY");
const requestId = process.env.MODELPORT_REQUEST_ID || randomUUID();
const payload = {
"model": "genjutsu-1.0",
"prompt": "A low camera moves along a misty river.",
"parameters": {
"resolution": "720p",
"aspect_ratio": "auto",
"generate_audio": false,
"n": 1
},
"references": [
{
"role": "reference_image",
"file_id": "REPLACE_WITH_UPLOADED_FILE_ID"
},
{
"role": "reference_video",
"file_id": "REPLACE_WITH_UPLOADED_FILE_ID"
}
]
};
for (const reference of payload.references) {
const variable = `MODELPORT_${reference.role.toUpperCase()}_ID`;
if (!process.env[variable]) throw new Error(`Set ${variable}`);
reference.file_id = process.env[variable];
}
async function api(path, data, requestKey) {
const headers = { Authorization: `Bearer ${key}` };
if (data) headers["Content-Type"] = "application/json";
if (requestKey) headers["Idempotency-Key"] = requestKey;
const response = await fetch(base + path, {
method: data ? "POST" : "GET", headers,
body: data && JSON.stringify(data), signal: AbortSignal.timeout(45_000),
});
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
return response.json();
}
const quote = await api("/v1/quotes", payload);
const cap = process.env.MODELPORT_MAX_PRICE_USD || quote.billing_price_usd;
console.log(`Request ID: ${requestId}, maximum charge: ${cap} USD`);
let job = await api("/v1/jobs", { ...payload, max_price_usd: cap }, requestId);
const jobId = job.id;
console.log("Job ID:", jobId);
for (let attempt = 0; attempt < 90 && !["succeeded", "failed"].includes(job.status); attempt++) {
await sleep(2_000);
job = await api(`/v1/jobs/${jobId}`);
}
console.log(JSON.stringify(job, null, 2));To retry the same submission, keep the payload and set MODELPORT_REQUEST_ID and MODELPORT_MAX_PRICE_USD to the values printed on the first run.
Use the quote to set max_price_usd on the same request to POST /v1/jobs.