English

Genjutsu 1.0 API

Find Genjutsu 1.0 model IDs, request examples, and current availability on ModelPort.

Model details and pricing

Call GET /v1/models with your key and check available before submitting.

Request parameters

ParameterAccepted valuesDefault
resolution480p, 720p, 1080p720p
aspect_ratioautoauto
generate_audiofalsefalse
n11

Reference files

Input modeRoles and allowed counts
referencereference_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.

Upload reference files

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.

Submit and poll a job