EN ZalogujZałóż konto
Startujemy w październiku 2026. Działają konta, katalog modeli, kalkulator i dokumentacja. Studio jest dostępne w podglądzie; generowanie czeka na uruchomienie.

Generowanie

Wszystkie strony dokumentacji

POST /v1/generate uruchamia generowanie obrazu, wideo albo audio. Zapytanie od razu zwraca zadanie (202). Wynik odbierasz, odpytując zadanie, dopisując ?wait=N albo przez webhook.

Zapytanie

http
POST https://jantaris.com/v1/generate
Authorization: Bearer sk-jt-...
Content-Type: application/json
PoleTypWymaganeOpis
modelstringtakId modelu mediów, np. seedance-2.5, gpt-image-2.5, mureka-v9
inputobjecttakParametry modelu, walidowane według input_schema modelu
webhook_urlstringnieAdres, na który przyjdzie POST, gdy zadanie się uda albo nie uda
Parametr zapytaniaTypOpis
waitinteger, 1-120Ile sekund serwer czeka na koniec zadania, zanim odpowie

Odpowiedź

Bez wait albo gdy zadanie nie zdążyło się skończyć, dostajesz 202 Accepted:

json
{
  "id": "task_8f2k...",
  "object": "task",
  "status": "queued",
  "model": "seedance-2.5",
  "estimated_cost": { "amount": "16.9204", "currency": "PLN" },
  "poll_url": "https://jantaris.com/v1/tasks/task_8f2k..."
}

Kwota w przykładzie dotyczy zapytania z sekcji Wideo z webhookiem (Seedance 2.5, 5 s, 720p) i pochodzi z cennika z dnia 2 października 2026 (konto PLN, z VAT). Aktualną kwotę zawsze zwraca API w estimated_cost. Liczysz ją tak:

  • wideo rozliczane za sekundę: cena za sekundę w wybranej rozdzielczości razy duration; cenę za sekundę dla każdej rozdzielczości znajdziesz w pricing.variants z GET /v1/models/{id};
  • przykład: cena za sekundę w 720p razy 5 s.

Z ?wait=N, jeśli zadanie skończy się w ciągu N sekund, dostajesz 200 OK i gotowe zadanie, czyli taki sam obiekt jak z GET /v1/tasks/{id}. Skończone zadanie ma status succeeded albo failed, więc zawsze sprawdzaj status.

Koszt i blokada środków

  1. Zanim zadanie ruszy, kwota estimated_cost zostaje zablokowana na saldzie. Jeśli dostępne saldo (available) jest niższe, zapytanie kończy się 402 insufficient_balance i nic się nie uruchamia.
  2. Przy succeeded pobierana jest dokładnie kwota cost, a blokada zostaje rozliczona.
  3. Przy failed blokada wraca w całości. Płacisz 0.

Kwoty to stringi z walutą: PLN na koncie polskim, USD na koncie globalnym. Patrz Rozliczenia.

Parametry wejścia

Każdy model ma własny schemat. Pobierz go z GET /v1/models/{id} (pole input_schema), zanim wyślesz zapytanie. Nieznane pola, zły typ albo wartość poza zakresem dają 422 invalid_request z komunikatem wskazującym błędne pole.

Najczęstsze pola według kategorii (konkretny model może obsługiwać tylko część):

KategoriaPola
Obrazprompt, negative_prompt, aspect_ratio (1:1, 16:9, 9:16, 4:3, 3:4), num_images (1-4, tylko w modelach, które mają je w GET /v1/models/{id}), image_urls (edycja albo referencje), seed
Wideoprompt, duration (sekundy), resolution (480p, 720p, 1080p zależnie od modelu), aspect_ratio, image_url (pierwsza klatka), generate_audio
Audio / muzykalyrics (w mureka-v9 wymagane), prompt (opis stylu); duration i instrumental tylko w modelach, które mają je w schemacie

Pola, które pominiesz, dostają wartość default ze schematu.

Obraz z czekaniem

Obrazy zwykle są gotowe w niecałą minutę, więc ?wait=60 daje wynik w jednym wywołaniu.

bash
curl "https://jantaris.com/v1/generate?wait=60" \
  -H "Authorization: Bearer $JANTARIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-2-pro",
    "input": {
      "prompt": "Zdjęcie produktowe ceramicznego kubka na betonowym stole, miękkie światło dzienne",
      "aspect_ratio": "4:3"
    }
  }'
python
import os, requests

API = "https://jantaris.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['JANTARIS_API_KEY']}"}

r = requests.post(
    f"{API}/generate",
    params={"wait": 60},
    headers=HEADERS,
    json={
        "model": "flux-2-pro",
        "input": {
            "prompt": "Zdjęcie produktowe ceramicznego kubka na betonowym stole, miękkie światło dzienne",
            "aspect_ratio": "4:3",
        },
    },
    timeout=130,  # dłużej niż wait
)
r.raise_for_status()
task = r.json()

if task["status"] == "succeeded":
    for item in task["output"]:
        print(item["url"], item.get("width"), item.get("height"))
elif task["status"] == "failed":
    print("błąd:", task["error"])
else:
    print("jeszcze trwa, odpytuj:", task["poll_url"])
javascript
const res = await fetch("https://jantaris.com/v1/generate?wait=60", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.JANTARIS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "flux-2-pro",
    input: {
      prompt: "Zdjęcie produktowe ceramicznego kubka na betonowym stole, miękkie światło dzienne",
      aspect_ratio: "4:3",
    },
  }),
});
const task = await res.json();
if (task.status === "succeeded") task.output.forEach((o) => console.log(o.url));
else console.log(task.status, task.poll_url ?? task.error);

Timeout klienta HTTP ustaw wyżej niż wait, inaczej klient zrezygnuje, zanim serwer odpowie.

Edycja obrazu

Obrazy źródłowe podajesz w image_urls, jeśli model to obsługuje (sprawdź input_schema):

bash
curl "https://jantaris.com/v1/generate?wait=60" \
  -H "Authorization: Bearer $JANTARIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "nano-banana-pro",
    "input": {
      "prompt": "Zamień tło na ośnieżone góry",
      "image_urls": ["https://example.com/zdjecie.jpg"]
    }
  }'

Wideo z webhookiem

Wideo trwa dłużej, więc uruchamiasz zadanie i czekasz, aż Jantaris da znać.

bash
curl https://jantaris.com/v1/generate \
  -H "Authorization: Bearer $JANTARIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.5",
    "input": {
      "prompt": "Slow dolly shot through a neon-lit night market in the rain",
      "duration": 5,
      "resolution": "720p",
      "aspect_ratio": "16:9"
    },
    "webhook_url": "https://twoj-serwer.example.com/jantaris-hook"
  }'
python
r = requests.post(
    f"{API}/generate",
    headers=HEADERS,
    json={
        "model": "seedance-2.5",
        "input": {
            "prompt": "Slow dolly shot through a neon-lit night market in the rain",
            "duration": 5,
            "resolution": "720p",
            "aspect_ratio": "16:9",
        },
        "webhook_url": "https://twoj-serwer.example.com/jantaris-hook",
    },
    timeout=30,
)
task = r.json()
print(task["id"], task["estimated_cost"])
javascript
const res = await fetch("https://jantaris.com/v1/generate", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.JANTARIS_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "seedance-2.5",
    input: {
      prompt: "Slow dolly shot through a neon-lit night market in the rain",
      duration: 5,
      resolution: "720p",
      aspect_ratio: "16:9",
    },
    webhook_url: "https://twoj-serwer.example.com/jantaris-hook",
  }),
});
const task = await res.json();
console.log(task.id, task.estimated_cost);

Większość modeli wideo rozliczasz za sekundę materiału: Seedance 2.5 kosztuje od 1,51 zł za sekundę, Kling 3.0 od 0,98 zł za sekundę. Veo 3.1 (Quality) jest liczony za klip: od 14,64 zł za film, patrz jednostki rozliczenia. Żeby ożywić zdjęcie, dodaj image_url (pierwsza klatka), jeśli schemat modelu ma to pole.

Muzyka

bash
curl https://jantaris.com/v1/generate \
  -H "Authorization: Bearer $JANTARIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mureka-v9",
    "input": {
      "lyrics": "[Verse]\nMiasto śpi, a ja nie\nNeon w oknie, kawa w dłoni\n[Chorus]\nJeszcze jedna noc, jeszcze jeden takt",
      "prompt": "lo-fi hip hop, warm vinyl crackle, mellow piano, soft female vocal"
    }
  }'

Mureka V9 generuje piosenkę z wokalem na podstawie tekstu. Pole lyrics jest wymagane, a zwrotki i refren oznaczasz w nim znacznikami [Verse] i [Chorus] (nowa linia jako \n w JSON-ie). Pole prompt jest opcjonalne i opisuje styl: gatunek, tempo, instrumenty, rodzaj wokalu. Model nie ma parametrów duration ani instrumental. Rozliczenie jest za utwór: 0,727 zł za utwór.

Błędy

Statuserror.typeKiedy
401authentication_errorZły albo brakujący klucz
402insufficient_balanceDostępne saldo niższe niż estimated_cost
403permission_errorKlucz osiągnął limit wydatków
404not_foundModel o takim id nie istnieje
422invalid_requestinput nie pasuje do schematu
429rate_limitPonad 60 zapytań na minutę na klucz (limit domyślny)
429rate_limit_error25 nieudanych generacji na koncie w ciągu 24 h, czas oczekiwania w nagłówku Retry-After

Zadanie, które wystartowało i potem się nie udało, nie jest błędem HTTP. Widzisz je jako status: "failed" z obiektem error, patrz Zadania. Pełna lista: Błędy.