דילוג לתוכן
תיעוד Nodaro
תיעודמדריך הרכיביםמודליםתבניותסוכני AI (MCP)מפתחיםאירוח עצמימחקרהשוואות
REST API

רכיבים

הרצת כל רכיב ב-REST API של Nodaro עם POST /v1/<node-type>‎, גילוי רכיבים, מודלים וערכי בוררים, ושליטה בפרומפט עם ייחוסים ומזהי הכוונה.

הרצת רכיב קוראת לרכיב אחד של Nodaro ישירות, בלי לבנות תהליך: שולחים POST /v1/<node-type> עם ההגדרות של הרכיב בגוף הבקשה. כל רכיבי היצירה בנויים כך, מ-generate-image ו-generate-video ועד text-to-speech, ונקודות הקצה של הגילוי מראות אילו רכיבים, מודלים והגדרות קיימים. רוב הרצות הרכיבים הן אסינכרוניות: התגובה היא jobId, ובעזרתו בודקים את הסטטוס מדי כמה שניות עד שהתוצאה מוכנה.

הרצת רכיב

הנתיב של סוג רכיב הוא POST /v1/ ואחריו הסוג, וגוף הבקשה הוא ההגדרות של הרכיב ב-JSON:

POST /v1/generate-image
Authorization: Bearer ndr_…
Content-Type: application/json

{ "prompt": "a lighthouse in a storm, oil painting", "provider": "nano-banana-pro", "aspectRatio": "3:4" }

מה שחוזר נקבע לפי הרכיב:

  • רכיבי יצירה מחזירים 200 עם { "jobId": "…" }. העבודה רצה ב-worker, ובודקים את הסטטוס של המשימה עם GET /v1/jobs/:id/status מדי כמה שניות, עד שהסטטוס שלה הוא completed. ראו את דף ה-API משימות.
  • יצירות של תמונה ווידאו עשויות להוסיף adjustments, רשימה של ההגדרות שהשרת תיקן כדי שיתאימו למודל שנבחר. הנתיבים generate-video ו-generate-image עשויים להוסיף גם warnings. ראו בדף ה-API תיקוני פרמטרים.
  • רכיבים שרצים מיד, כגון combine-text, מחזירים את התוצאה המלאה שלהם מיד, בלי jobId.
  • רכיבי גריפה, כגון web-scrape, גם הם עונים מיד. התגובה שלהם כוללת גם jobId, בשביל ההיסטוריה שלכם, וגם את הנתונים עצמם.

כשיצירה מתחילה, משוריינים לה קרדיטים. כשאין בחשבון מספיק קרדיטים להרצה, הקריאה נדחית עם 402 insufficient_credits.

רכיבים עם נתיב ארוך יותר

רוב רכיבי הטקסט שקוראים למודל שפה פועלים לפי אותו כלל של POST /v1/<node-type>: generate-script, image-critic, qa-check ו-describe-to-picker. כמה אחרים רשומים תחת נתיב ארוך יותר:

סוג הרכיבנתיב
llm-chatPOST /v1/llm-chat/generate
after-effectsPOST /v1/after-effects/generate
motion-graphicsPOST /v1/motion-graphics/generate
lottie-overlayPOST /v1/lottie-overlay/generate
3d-titlePOST /v1/3d-title/generate
image-to-textPOST /v1/image-to-text/describe
video-composerPOST /v1/scene-graph/generate

המתודה client.nodes.run(type, params) של ה-SDK והפקודה nodaro nodes run של ה-CLI שולחות בשבילכם כל אחד מסוגי הרכיבים האלה לנתיב שלו. ראו את הדף הרצת רכיבים ב-SDK.

נתיבים של מודלי שפה מקבלים שני שדות אופציונליים:

  • reasoningEffort: none, low, medium, high, xhigh או max, לפי המודל. השמיטו את השדה, או בחרו רמה שהמודל לא תומך בה, כדי לקבל את ברירת המחדל של המודל עצמו. לרמה אין מחיר משלה. הקריאה מחויבת לפי הטוקנים שהיא השתמשה בהם, ולכן רמה גבוהה יותר עולה יותר רק בגלל החשיבה שהמודל כותב. במודל Claude, בחירה של רמה כלשהי מריצה את הקריאה ב-API הישיר של Anthropic, בתעריף של ה-API הזה.
  • advancedMode: true: מודלי Gemini ו-Claude. הבקשה רצה ב-API של יצרן המודל עצמו, השירות היחיד שבו temperature, maxTokens וכל טווח החשיבה נכנסים לתוקף. הקריאה מחויבת בתעריף לטוקן של השירות הזה. בקשה עם מודל שאין לו שירות כזה נדחית עם 400 advanced_mode_unsupported. כל עוד הספק של המודל עצמו לא יכול לקבל בקשות, הבקשה נדחית, במקום לרוץ בשירות ברירת המחדל, שבו ההגדרות האלה לא היו נכנסות לתוקף. התגובה היא 400 advanced_mode_unavailable לפני שנגבים קרדיטים, או 502 advanced_mode_unavailable באמצע הקריאה. על דחייה באמצע הקריאה הקרדיטים מוחזרים, אלא אם הספק חייב על הניסיון. כבו את המצב המתקדם כדי להריץ את המודל בשירות ברירת המחדל שלו.

הרכיב describe-to-picker מחזיר את התוצאה שלו באותה בקשה, והוא יכול גם להזרים את התשובה כאירועי שרת (SSE). ראו את הדף תיאור לבורר. השדות של generate-script מופיעים בדף יצירת תסריט.

דוגמה: יצירת תמונה

התחלת המשימה

curl -s -X POST https://app.nodaro.ai/v1/generate-image \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "prompt": "a knight on a hill at dawn, cinematic",
        "provider": "nano-banana-pro",
        "aspectRatio": "16:9",
        "resolution": "2K"
      }'
{ "jobId": "0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10" }
import { createClient, StaticTokenAuth } from '@nodaro/sdk'

const client = createClient({
  baseUrl: 'https://app.nodaro.ai',
  auth: new StaticTokenAuth(process.env.NODARO_API_KEY!),
})

const result = await client.nodes.run('generate-image', {
  prompt: 'a knight on a hill at dawn, cinematic',
  provider: 'nano-banana-pro',
  aspectRatio: '16:9',
  resolution: '2K',
})
nodaro nodes run generate-image \
  --param prompt="a knight on a hill at dawn, cinematic" \
  --param provider=nano-banana-pro \
  --param aspectRatio=16:9 \
  --param resolution=2K

בדיקת הסטטוס של המשימה

בקשו את הסטטוס של המשימה כל 2–5 שניות, עד שהוא completed או failed:

curl -s https://app.nodaro.ai/v1/jobs/0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10/status \
  -H "Authorization: Bearer $NODARO_API_KEY" | jq -r .data.status

קריאת התוצאה

משימת תמונה שהסתיימה כוללת את הכתובת של התמונה ב-output_data.imageUrl. משימת וידאו משתמשת ב-videoUrl, משימת אודיו ב-audioUrl, ובמשימות רבות יש גם thumbnailUrl.

{
  "data": {
    "id": "0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10",
    "status": "completed",
    "progress": 100,
    "output_data": { "imageUrl": "https://…/0f1a9c2e.png" },
    "error_message": null
  }
}

ה-SDK וה-CLI יכולים לבדוק את הסטטוס בשבילכם:

const output = await client.nodes.runAndWait('generate-image', {
  prompt: 'a knight on a hill at dawn, cinematic',
  provider: 'nano-banana-pro',
})
console.log(output.imageUrl)

// Several candidates at once, in input order:
const results = await client.nodes.runMany('generate-image', [
  { prompt: 'a knight on a hill, sunrise' },
  { prompt: 'a knight on a hill, golden hour' },
  { prompt: 'a knight on a hill, blue hour' },
])
for (const { jobId, output } of results) console.log(jobId, output.imageUrl)
nodaro nodes run generate-image \
  --param prompt="a knight on a hill at dawn, cinematic" \
  --param provider=nano-banana-pro \
  --watch --json | jq -r '.output_data.imageUrl'

כברירת מחדל, המתודה runAndWait בודקת את הסטטוס כל 2,000 אלפיות שנייה, עד 15 דקות. אפשר לשנות את זה עם pollMs ו-maxMs, לעצור את ההמתנה עם AbortSignal ב-signal, ולקבל עדכוני התקדמות עם onProgress. המתודה זורקת שגיאות עם טיפוס, שאפשר לתפוס עם instanceof:

שגיאהמתי
InsufficientCreditsError, StorageExceededError, JobBlockedErrorההרצה נדחתה לפני שמשימה כלשהי התחילה.
ModelUnavailableErrorהפריסה הזו לא מציעה את המודל, או שמנהל כיבה אותו. בחרו מודל אחר.
JobFailedErrorהמשימה הסתיימה בסטטוס failed או cancelled. השגיאה כוללת את jobId ואת הודעת השגיאה.
JobTimeoutErrorעבר הזמן שהוגדר ב-maxMs. המשימה לא מבוטלת, ובדרך כלל היא עדיין מסתיימת: קבלו אותה מאוחר יותר עם client.jobs.get(jobId).
JobAbortedErrorה-signal שלכם הופעל.
JobHeldErrorהמשימה נכנסה לסטטוס pending_review בפריסה שבודקת תוצאות. המשימה לא מבוטלת: בדקו שוב מאוחר יותר.

ב-CLI, העבירו גוף בקשה מורכב, כגון מערכים או אובייקטים מקוננים, בקובץ, עם --params-file body.json. ערכי הדגלים גוברים על הקובץ באותו מפתח, והערכים true, false, null ומספרים מומרים מטקסט.

הגדרות של רכיב יצירת תמונה

השדות שלמטה הם ההגדרות הנפוצות ביותר של POST /v1/generate-image. מה כל הגדרה עושה בעורך מוסבר בדף יצירת תמונה, ובמה כל מודל תומך מופיע בדפי מודלי התמונה.

מאפיין

סוג

עריכה עם מסכה או עידון עולה כמו יצירה חדשה באותו מודל.

הנתיב /v1/generate-image יכול להחזיר warnings, רשימה של { code, message }, על משהו שביקשתם ולא נשלח. כרגע הקוד היחיד הוא moodboard_images_not_sent: חלק מהתמונות של מודבורד לא נכנסו במגבלת הייחוסים של המודל. ההרצה ממשיכה, והמשימה שומרת את אותן אזהרות ב-input_data.warnings.

החלת ערכה

הנתיב POST /v1/generate-image מקבל presetId: מזהה מובנה, כגון generate-image/cinematic-still, או ה-uuid של אחת הערכות שלכם. את המזהים המובנים מחזיר הנתיב GET /v1/node-presets/factory?nodeType=generate-image, שלא צריך אסימון. הנתיב מחיל את הערכה כמו שהעורך מחיל אותה על רכיב יצירת תמונה, ולכן המשימה זהה לזו שהכפתור הרצה בעורך היה שולח:

  • הפרומפט של הערכה, והטקסט לפני ואחרי שלה (promptPrefix ו-promptSuffix).
  • משתני {name || default}, עם ערכי ברירת המחדל שלהם.
  • ה-style של הערכה, שמשולב בפרומפט.
  • הפרומפט השלילי של הערכה: במודל שמקבל פרומפט שלילי הוא נשלח בשדה המיועד לכך, ובכל מודל אחר הוא מתווסף לפרומפט כשורת Avoid: (להימנע מ:).
  • ההגדרות של הערכה, וברירות המחדל של העורך להגדרות שהיא לא קובעת: המודל gpt-image-2 והיחס 16:9. המודל והמחיר זהים לאלה שבעורך.

שדות ששולחים גוברים על הערכה, כמו עריכה ברכיב שהערכה הוחלה עליו. ה-prompt שלכם מחליף את הפרומפט של הערכה, והטקסט לפני ואחרי של הערכה עוטף אותו. השדות provider, aspectRatio, resolution, quality, negativePrompt, style ושאר ההגדרות מחליפים את הערכים של הערכה. הייחוסים, sessionId ו-origin נשמרים.

curl -s -X POST https://app.nodaro.ai/v1/generate-image \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presetId": "generate-image/logo-wordmark", "presetVariables": {"BRAND": "Acme"}}'
  • משתנה בלי ברירת מחדל, כגון {BRAND}, צריך ערך ב-presetVariables. בלי ערך, הנתיב מחזיר 400 עם code: "preset_variables_required" ועם tokens: ["BRAND"].
  • presetId לא מוכר נדחה עם 404 preset_not_found.
  • בדיקת הקרדיטים מתמחרת את הבקשה אחרי שהערכה מוחלת. השדות presetId ו-presetVariables לא נשמרים במשימה.
  • בערכה שעובדת מתמונות, הערך של minReferences גדול מ-0. שלחו את מספר התמונות הזה ב-referenceImageUrls. ראו את דף ה-API ערכות.
  • ערכה משתלבת עם count ועם models. ראו את הסעיף הבא.
  • ערכה לא יכולה להשתמש בפלטות או במודבורדים שלכם. כשה-direction שלה מציין palette:<id> או moodboard:<id>, בין שאתם שלחתם אותו ובין שהוא שמור בערכה, הנתיב מחזיר 400 validation_error, והשדה field מציין את המפתח. התגובה מגיעה לפני שמשהו נוצר ולפני שנגבים קרדיטים.

כמה תמונות בקריאה אחת

הנתיב POST /v1/generate-image יכול ליצור כמה תמונות בבת אחת:

  • count (מ-1 עד 4) יוצר את מספר התמונות הזה ממודל אחד. כל תמונה היא משימה משלה.
  • models (מ-2 עד 4 מזהים שונים של מודלי תמונה, אותם מזהים ש-provider מקבל) מחליף את provider ושולח את אותה בקשה לכל מודל. ההגדרות של כל מודל מותאמות אליו כמו בקריאה יחידה, והתיקונים מדווחים לכל מודל בנפרד.
  • עם שניהם, השדה count חל על כל מודל: הערך models: ["gpt-image-2", "flux-2-max"] עם count: 2 יוצר ארבע תמונות. בקשה אחת יוצרת לכל היותר 8 תמונות.
curl -s -X POST https://app.nodaro.ai/v1/generate-image \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0f8e6c1a-try-1" \
  -d '{"prompt": "a lighthouse at dusk", "models": ["gpt-image-2", "flux-2-max"], "count": 2, "seed": 41}'
{
  "jobId": "<first job>",
  "jobIds": ["<job 1>", "<job 2>", "<job 3>", "<job 4>"],
  "batchId": "6b1f7e2a-0c4d-5e8f-9a1b-2c3d4e5f6a7b",
  "groups": [
    { "model": "gpt-image-2", "jobIds": ["<job 1>", "<job 2>"], "credits": <credits> },
    { "model": "flux-2-max", "jobIds": ["<job 3>", "<job 4>"], "credits": <credits>,
      "adjustments": [{ "field": "resolution", "from": "1K", "to": "2 MP", "reason": "..." }] }
  ],
  "totalCredits": <credits>
}

על כל תמונה משלמים כמו על קריאה יחידה שמבקשת אותה. בלי count ו-models, או עם count: 1, התגובה היא ה-{ "jobId" } הרגיל. השדה jobId הוא תמיד המשימה הראשונה, ולכן קוד שקורא אותו ממשיך לעבוד.

  • קרדיטים: על כל האצווה, או כלום. היתרה נבדקת מול הסכום הכולל של האצווה לפני שמשהו נוצר. כשאין מספיק, הנתיב מחזיר 402 insufficient_credits, עם הסכום הכולל ב-required, ושום דבר לא נוצר. כשחיוב נכשל באמצע, הקרדיטים על המשימות שכבר נוצרו מוחזרים, והמשימות נמחקות לפני התגובה.
  • אידמפוטנטיות, לכל תמונה. עם Idempotency-Key: K, המפתח של תמונה i הוא K:i. בקשה חוזרת עם אותו מפתח מחזירה את אותם מזהי משימות, ואף פעם לא גורמת לחיוב כפול של משימה. אצווה שנוצרה רק בחלקה נוצרת עד הסוף. בקשה שנייה עם אותו מפתח, באותו זמן, ממתינה לראשונה, או נדחית עם 409 batch_in_progress אחרי 15 שניות; שלחו אותה שוב. שימוש חוזר במפתח עם גוף בקשה אחר נדחה עם 422 idempotency_key_reused.
  • זרעים. עם seed, תמונה i של כל מודל מקבלת seed + i, כך שהתמונות שונות זו מזו.
  • עם ערכה, השדה count יוצר N תמונות מהבקשה של הערכה. עם models, הערכה מוחלת פעם אחת לכל מודל, כך שכל מודל מקבל את הבקשה שהעורך היה שולח אליו.
  • מציאת אצווה מאוחר יותר. בכל משימה של האצווה מופיעים אותו input_data.batchId והמיקום שלה ב-input_data.batchIndex. הנתיב GET /v1/jobs?batchId=<id> מחזיר את כל המשימות האלה.
  • דחייה לפני שמשהו נוצר. הנתיב מחזיר 400 validation_error על count מחוץ לטווח 1–4, על פחות מ-2 או יותר מ-4 מודלים ב-models, על מודל שחוזר פעמיים או מודל לא מוכר, על models יחד עם provider, או על יותר מ-8 תמונות. על מודל שהפריסה לא מציעה התגובה היא 403 model_not_available.

יצירת מסכה

הנתיב POST /v1/generate-mask מסמן בתמונה נושא שמתואר בטקסט, ומחזיר תמונת מסכה בשחור־לבן. הלבן הוא הנושא. גוף הבקשה הוא { imageUrl, prompt, threshold? }:

  • השדה prompt מקבל מ-1 עד 500 תווים, למשל "the person" (האדם).
  • השדה threshold הוא ערך בין 0 ל-1, וברירת המחדל היא 0.3. ערך נמוך יותר מסמן יותר.

גוף בקשה פגום נדחה עם 400 validation_error. התגובה היא { jobId }. הפלט של משימה שהסתיימה הוא { maskUrl, imageUrl }: השדה maskUrl הוא קובץ ה-PNG של המסכה, והשדה imageUrl הוא תמונת המקור, שמועברת בלי שינוי. העבירו את שניהם לעריכה עם השלמה. הרצה עולה 55 קרדיטים, והנתיב GET /v1/credits/model-cost?model=generate-mask מחזיר את אותו מחיר. ראו את הדף יצירת מסכה.

יצירת וידאו

שני נתיבים יוצרים וידאו. הנתיב POST /v1/generate-video מנפיש מתמונות: פריים פתיחה ב-imageUrl, פריים סיום אופציונלי ב-endFrameUrl, או ייחוסים בלבד במודלים שמקבלים אותם. הנתיב POST /v1/text-to-video יוצר קליפ מפרומפט בלבד, ולכן prompt הוא שדה נדרש בו. כשמשמיטים את provider, הפלטפורמה משתמשת במודל הווידאו שמוגדר אצלה כברירת מחדל.

הנתיב POST /v1/text-to-video מקבל גם ערך בוליאני אופציונלי, contentPolicyRewrite. כשהוא חסר או true, אחרי דחייה בגלל זכויות יוצרים יש ניסיון חוזר אחד עם פרומפט בניסוח אחר, ואז הפלט של המשימה כולל contentPolicyRewrite: { original, rewritten }. עם false, דחייה בגלל זכויות יוצרים מכשילה את המשימה.

{
  "imageUrl": "https://…/frame.png",
  "provider": "seedance-2",
  "prompt": "she turns toward the window",
  "duration": 8,
  "resolution": "720p",
  "direction": { "cameraMotion": "dolly-in", "timeOfDay": "dawn" }
}

התגובה היא { "jobId": "…" }, עם warnings ו-adjustments כשהם רלוונטיים. במשימה שהסתיימה מופיע output_data.videoUrl.

מאפיין

סוג

כמה כללים משתנים ממודל למודל:

  • במשפחת Seedance 2, resolution ו-aspectRatio מועברים כמו שהם: המודל מתעלם מערך שהוא לא תומך בו, ואף פעם לא דוחה אותו. Seedance 2 הוא היחיד עם 4k ו-adaptive. Seedance 2.5 יוצר עד 30 שניות בקריאה אחת, ועם פריים פתיחה הוא תמיד מרנדר ביחס הגובה־רוחב של אותו פריים.
  • MiniMax H3 מקבל ב-resolution את 2K או את 768P, בדיוק בכתיב הזה. הנתיב GET /v1/nodes/:type מציג ב-providerResolutionWire את הערך שצריך לשלוח.
  • אפשר לשלב פריימים וייחוסים ב-Seedance 2 וב-MiniMax H3. כששולחים ייחוס לצד פריים פתיחה או פריים סיום, הפריימים הופכים לייחוסים ממוספרים בפרומפט, במקום נקודות התחלה וסיום קבועות. Wan 3.0 לא יכול לשלוח את שניהם, ולכן הפריים מתווסף במקום זאת לסוף רשימת הייחוסים, והקריאה עדיין מצליחה.
  • סרטוני ייחוס עולים יותר. במודלים שגובים תשלום על סרטוני ייחוס, קליפ ייחוס מתומחר לפי האורך שלו ועוד אורך הפלט, ולכן על קליפ מקור ארוך יותר משוריינים יותר קרדיטים. Wan 3.0 גובה רק לפי שניות הפלט. Kling 4.0 גובה לפי הפלט ועוד הארוך מבין הפלט והקליפים, ולכן קליפ קצר מהפלט נחשב באורך הפלט.
  • characterReferences שומר על הפנים של אדם אמיתי ב-Gemini Omni וב-Gemini Omni Flash. כל רשומה היא { imageUrl, description, bodyImageUrl?, name?, voice? }: פורטרט, תיאור של האדם עד 2,000 תווים, תמונת גוף מלא אופציונלית ושם אופציונלי עד 100 תווים. השדה referenceImageUrls הוא הקשר כללי בשביל המודל, ואילו הקלט הזה שומר על הפנים. בכל מודל אחר הבקשה נדחית עם 400 character_references_unsupported. פריים פתיחה או פריים סיום באותה בקשה גורמים לדחייה עם 400 character_references_with_start_frame או 400 character_references_with_end_frame. הבקשה חייבת להיכנס בתקציב הקלטים של המודל, 7 יחידות: כל תמונה נחשבת 1, כל סרטון 2, וכל דמות 1, או 2 עם bodyImageUrl. בקשה שחורגת מהתקציב נדחית עם 400 character_references_quota. על ייחוסי דמויות אין תוספת מחיר.
  • Kling 4.0 (kling-4) רץ מטקסט בלבד, או מחומרי ייחוס, עד 15 חומרים בסך הכול. הוא מקבל referenceImageUrls (עד 10), referenceVideoUrls (עד 5, כל אחד באורך 2–30 שניות), characterReferences (עד 7) ו-referenceAudioUrls (עד 3). בקשה עם יותר מזה נדחית עם 400 עוד לפני שמשוריינים קרדיטים: הקוד character_references_quota כשהבקשה כוללת characterReferences, והקוד validation_error בכל מקרה אחר. השדות imageUrl או endFrameUrl נחשבים לתמונה: הם מצטרפים לתמונות הייחוס אחרי התמונות שלכם, והפרומפט מציין אותם כפריים הפותח או כפריים הסוגר. כל ייחוס דמות הוא נושא עם שם: השדות imageUrl, bodyImageUrl ועד 3 extraImageUrls הם 2–4 התמונות שלו, והפרומפט קורא לו @<name>. רשומה עם תמונה אחת נשלחת כתמונת ייחוס רגילה. מותר לשלב עם ייחוסי דמויות פריים פתיחה או פריים סיום, אבל רשומה עם voice נדחית עם 400 character_voice_unsupported; שלחו קליפי קול ב-referenceAudioUrls. בפרומפט, קראו לחומרים @image_N, @video_N, @<name> ו-@audio_N. כשהפרומפט מזכיר חומר שהבקשה לא כוללת, ה-@ שלו מוסר, כך שההרצה עדיין מתחילה. הרצה עם סרטון ייחוס מחויבת לפי כל שנייה של הפלט ועוד הארוך מבין הפלט וסרטוני הייחוס, בתעריף של הרצה עם ייחוסים.
  • פסקול אודיו ב-Kling 4.0 (מופעל כברירת מחדל). הקליפ הראשון ב-referenceAudioUrls מתנגן כפסקול של התוצאה. הוא נשלח כעוד סרטון ייחוס: פריים סטטי עם האודיו, באורך האודיו, 2 שניות לפחות ולכל היותר כאורך הפלט. הסאונד שלו נשמר, ולכן האנשים בסצנה משחקים בדיוק לפי הרצועה. שאר הקליפים נשארים קולות עם שם, והאסימון @audio_2 הופך ל-@Voice1. הפסקול תופס אחד מ-5 המקומות של סרטוני הייחוס, וההרצה מחויבת כהרצה עם סרטון ייחוס. עם audioSoundtrack: false, כל קליפ נשאר דגימת קול. עם הפסקול, Kling שומר גם על הסאונד של סרטוני הייחוס ששולחים.
  • Kling 4.0 Keyframes (kling-4-keyframes) מקבל פריים פתיחה ב-imageUrl, עד 8 פריימי ביניים ב-referenceImageUrls, לפי הסדר, ופריים סיום ב-endFrameUrl. מותר לשלוח פריים סיום לבדו, ובלי אף פריים ההרצה היא טקסט לווידאו. השדה duration מגביל את מספר הפריימים הכולל: 4 ב-3 שניות, עוד פריים אחד על כל שנייה נוספת, ו-10 החל מ-9 שניות. בקשה עם יותר פריימים, או עם יותר מ-8 פריימי ביניים, נדחית עם 400 validation_error עוד לפני שמשוריינים קרדיטים. בפרומפט, הפריימים הם @first_frame, @keyframe_N ו-@last_frame, והאסימון @image_N משוכתב ל-@keyframe_N. השדה aspectRatio חל רק כשאין אף פריים. המודל לא מקבל סרטוני ייחוס, אודיו או דמויות.
  • שני מודלי Kling 4.0 מקבלים duration של 3–30 שניות שלמות (ברירת המחדל 5) ו-resolution של 720p (ברירת המחדל) או 1080p; כל רזולוציה אחרת מרונדרת ב-720p ומשלמים עליה כמו על 720p. השדה aspectRatio הוא auto (ברירת המחדל: הוא מתאים את עצמו לחומרים, ו-16:9 כשאין חומרים), 16:9, 9:16, 1:1 או 21:9. הסאונד תמיד מופעל (sound לא נלקח בחשבון), אין seed, והפרומפט יכול להכיל עד 8,000 תווים. המחיר שלהם הוא לפי שנייה, והם לא זמינים במסלול החינמי.
  • voice מצמיד קול אחד לייחוס דמות לאורך כמה קליפים: { preset, description?, exampleLine? }, כשהשדה preset הוא אחד ממזהי הקולות של Gemini. בקשה יכולה להצמיד עד 3 קולות שונים; אחרת היא נדחית עם 400 character_voices_over_limit. ראו את הדף יצירת וידאו לרשימת הקולות.

האורכים, הרזולוציות ומחירי הקרדיטים של כל מודל מופיעים בדפי מודלי הווידאו, והנתיב GET /v1/models מחזיר אותם.

שימוש בייחוסים

ייחוסים הם תמונות, ובווידאו גם קליפים ואודיו, שהמודל צריך להתאים אליהם. אפשר לשלוח אותם כרשימה שטוחה של כתובות, או כייחוסים בפורמט מובנה, שהנתיב ממספר, מתייג וכותב לפרומפט בשבילכם, בדיוק כמו שהעורך עושה עם רכיבים מחוברים.

ייחוסים בפורמט מובנה

הנתיבים POST /v1/generate-image, POST /v1/generate-video, POST /v1/text-to-video ו-POST /v1/extend-video מקבלים connectedReferences. כל רשומה מתארת תמונה אחת:

מאפיין

סוג

בנתיבי הווידאו, הנתיב הופך את הרשומות האלה לייחוסים ממוספרים:

  • כל ייחוס שלא מזכירים מצורף. הכתובת שלו מצטרפת לרשימת הייחוסים, בלי כפילויות, והוא מקבל שורה כמו @image_1 (reference): <label>. רשומה של wired-character הופכת במקום זאת לחלק מההוראה "Use these characters:" (השתמש בדמויות האלה:).
  • הרשימה נחתכת במגבלה של המודל לפני המספור, כך שמספר ייחוס בפרומפט אף פעם לא מפנה לתמונה שלא נשלחה.
  • {image:N:label} בפרומפט הופך ל-"the label from @image_N" (התווית מ-@image_N), וממוספר לפי הייחוסים המצורפים.
  • {ref:<id>} ו-{ref:<id>:label} מפנים לייחוס לפי ה-id שנתתם לו. הפלטפורמה מחליפה את האסימון במספר של הייחוס אחרי שהיא ממספרת את הרשימה, כך שאף פעם לא צריך לחשב מספר בעצמכם. סדר המספור: קודם referenceImageUrls השטוחה, אחר כך דמויות שלא הזכרתם, ואחר כך שאר הרשומות, בסדר שלכם. אסימון שהייחוס שלו לא צורף, כי הוא חרג מהמגבלה או כי המודל לא מקבל ייחוסים, מוחלף בתווית שלו; אם אין תווית, ב-defaultName; ואם גם הוא חסר, האסימון מוסר בלי תחליף. האסימון אף פעם לא מגיע למודל כטקסט גולמי.
  • referenceOrder, רשימה של מזהי ייחוסים, משנה את סדר הייחוסים וממספר אותם מחדש בהתאם. גם הנתיב POST /v1/generate-image מקבל אותו.

עותקי תצוגה מוחלפים בקבצים המקוריים. זה חל על כל קלט תמונה ב-POST /v1/generate-video וב-POST /v1/text-to-video: imageUrl, endFrameUrl, referenceImageUrls, ייחוסים מחוברים וייחוסי דמויות. קלט שהוא עותק תצוגה בגודל מותאם של תמונה ב-CDN של Nodaro, https://cdn.nodaro.ai/cdn-cgi/image/<options>/<path>, נשמר ונשלח כקובץ המקורי, https://cdn.nodaro.ai/<path>. אותו דבר חל על התמונות של הרצת טרנד ושל הרצת Nodaro Motion. בכתובות בשרתים אחרים משתמשים כמו שנשלחו.

מטא־דאטה מוטמע מוסר לפני שמודל רואה תמונה. בחלק מתמונות הקלט יש נתונים מוטמעים, כגון Content Credentials, EXIF, XMP, IPTC או מקטעי טקסט של PNG. תמונה כזו מקודדת מחדש בלי הנתונים האלה, בפורמט שלה, לפני שהיא נשלחת למודל. תמונה נקייה נשלחת כמו שהיא. הקובץ השמור שלכם לא משתנה.

השדה connectedReferences מעביר תמונות בלבד. השדות referenceVideoUrls ו-referenceAudioUrls נשארים רשימות שטוחות. בלי connectedReferences, הנתיבים מתנהגים כמו קודם: ה-prompt וה-referenceImageUrls שלכם נשלחים כמו שהם.

ב-POST /v1/generate-image ובכלי ה-MCP generate_image, אסימון {image:N} או {image:N:label} ב-prompt מפנה לתמונת הייחוס ה-N:

  • בלי ייחוסים מחוברים, N סופר את referenceImageUrls השטוחה לפי הסדר, כך שהאסימון {image:1} הוא הכתובת הראשונה ששלחתם. זה כולל בקשה שהייחוסים האחרים היחידים בה הם describedReferences.
  • עם רשומה אחת לפחות ב-connectedReferences, N סופר את הרשומות של connectedReferences לפי הסדר. כתובות referenceImageUrls שטוחות באותה בקשה עדיין מצורפות, לפני המחוברות, אבל אף אסימון לא מפנה אליהן. כדי להפנות לתמונה בפרומפט, שלחו אותה כרשומה ב-connectedReferences.
  • אסימון שאין תמונה במיקום שלו הופך לתווית שלו: מ-{image:2:person} נשאר person. האסימון {image:2} בלי תווית מושמט.

העורך והרצת תהליך ממספרים את האסימונים באותו אופן. גם תמונה שמגיעה לרכיב יצירת תמונה דרך רכיב ביניים, כגון רכיב טקסט, נשלחת וממוספרת.

אילו מודלי וידאו מקבלים תמונות ייחוס

משפחת מודליםתמונות ייחוס
משפחת Seedance 2עד 9
HappyHorse Ref2Vעד 9
Gemini Omni, Kling 3 Omni, Grok Imagine מתמונה לווידאועד 7
VEO 3.1 Fast ו-VEO 3.1 Liteעד 3

בכל מודל אחר, אסימוני {image:N} מצטמצמים לתוויות שלהם, ושום דבר לא מצורף. VEO 3.1 Quality לא נמצא ברשימה: המודל מתעלם מייחוסים שנשלחים עם veo3, וההרצה משתמשת בפריימים שלה.

וידאו מייחוסים בלבד

ב-POST /v1/generate-video, פריים הפתיחה הוא אופציונלי כשהמודל תומך לפחות בסוג אחד של הייחוסים ששולחים, למשל Kling 3 Omni עם referenceImageUrls בלבד. הרצה מייחוסים בלבד ב-VEO 3.1 Fast או ב-Lite עוברת למצב ייחוסים מעצמה, כך שאין צורך ב-generationType. סוג ייחוס שהמודל לא יכול להשתמש בו לא נחשב: ייחוסי אודיו בלבד, במודל שמקבל רק תמונות, נדחים עם 400.

פריים סיום לבדו מתקבל במודלים שמצרפים אותו לייחוסים שלהם: משפחת Seedance 2, MiniMax H3 ו-Wan 3.0. שלחו את endFrameUrl פעם אחת, בלי לחזור על התמונה ב-referenceImageUrls. החבילה @nodaro/shared מייצאת את videoProviderFoldsLoneEndFrame(provider), כדי שהממשק שלכם יוכל להשתמש באותו כלל.

כשבבקשה אין פריים פתיחה, אין מצב ייחוסים ואין ייחוס שהמודל יכול להשתמש בו, התגובה נקבעת לפי המודל:

  • במודל שלא יכול ליצור וידאו מטקסט בלבד, כגון Kling 3 Omni, HappyHorse Ref2V או Hailuo 2.3, הבקשה נדחית עם 400 image_required. ההודעה מציינת אם ייחוסים יעבדו במקום זאת. הנתיב GET /v1/models הוא המקור הקובע לשאלה אילו מודלים אלה.
  • בכל מודל אחר הבקשה נדחית עם 400 validation_error, וההודעה מפנה אתכם ל-POST /v1/text-to-video ליצירת קליפ מפרומפט בלבד.

הרחבת וידאו

הנתיב POST /v1/extend-video מקבל connectedReferences ו-referenceImageUrls רק עם provider: "seedance-2-extend". כל מודל הרחבה אחר דוחה אותם עם 400. המגבלה היא 8 תמונות שלכם, כי הפריים האחרון של קליפ המקור תופס מקום אחד ברשימת הייחוסים, אחרי התמונות שלכם, כך שהמספרים שלכם אף פעם לא זזים. 2 השניות האחרונות של המקור נשלחות כ-@video_1, והמחיר שלהן כבר כלול בתעריף ההרחבה: תמונות ייחוס לא מוסיפות קרדיטים. לרכיב הרחבת וידאו אין direction ואין subject, כי הפרומפט שלו ממשיך קליפ שכבר יש לו מראה.

ייחוסים מתוארים

השדה describedReferences נותן שם לנושא שאפשר לתאר אבל עדיין אין לכם תמונה שלו, כגון תפקיד בתסריט. הנתיבים POST /v1/generate-image, /v1/generate-video, /v1/text-to-video ו-/v1/extend-video מקבלים עד 10 רשומות של { name, description }. השם יכול להכיל עד 80 תווים, והתיאור עד 2,000.

  • שום דבר לא מצורף. ייחוס מתואר לא תופס מקום ברשימת הייחוסים, והמספור של שאר הייחוסים לא משתנה.
  • הוא מגיע למודל כשורת טקסט: <Name> — <description>. השאירו את השם בפרומפט, למשל Natalie walks down the pier. (Natalie הולכת לאורך המזח), והשורה מסבירה למודל מי זו Natalie. אל תכתבו בשבילו אזכור עם @: התחביר הזה מפנה לתמונה מצורפת.
  • הוא עובד לבד. שלחו describedReferences בלי שום connectedReferences, כמו במקרה הרגיל של סיפור שנכתב לפני שקיימת דמות כלשהי.
  • רשומות בלי שם או בלי תיאור נשמטות, ושם שחוזר נכתב פעם אחת. כל מודלי ההרחבה מקבלים ייחוסים מתוארים, כי אין בהם כתובת.

תיאורים להרצה אחת וכיתובים

  • descriptionOverride ברשומה של connectedReferences אומר מה הייחוס בהרצה הזו בלבד, עד 2,000 תווים. הוא נכנס למקום התיאור שכבר יש בהוראה של הייחוס, וגובר על התיאור השמור. כשאין להוראה תיאור, הוא מוסיף שורה אחת, כך שהמודל מקבל את המידע פעם אחת, אף פעם לא פעמיים.
  • referenceVideoCaptions ו-referenceAudioCaptions ב-POST /v1/generate-video וב-/v1/text-to-video מתארים את קליפי הייחוס ואת האודיו, עד 500 תווים כל אחד. הם מיושרים לפי אינדקס: הרשומה referenceVideoCaptions[0] מתארת את referenceVideoUrls[0]. כל כיתוב הופך לשורה כמו @video_1: <caption>., ורשומה ריקה מדלגת על קליפ אחד בלי לשבור את היישור.

אזכור ייחוס בפרומפט

ב-POST /v1/generate-image אפשר למקם ייחוס בתוך המשפט, במקום להשאיר אותו ברשימה שבסוף. כתבו @<name-slug>:<index>, או @<name-slug>:<index>:<role> כדי לציין מה לקחת ממנו:

{
  "prompt": "a wide shot of @nessie:1 rising beside @dock:2:material",
  "connectedReferences": [
    { "id": "cr-1", "defaultName": "Nessie", "source": "wired-creature", "url": "https://…/nessie.png" },
    { "id": "ob-1", "defaultName": "Dock", "source": "wired-object", "url": "https://…/dock.png" }
  ]
}

המודל מקבל "a wide shot of the creature from reference image A rising beside the material from reference image B" (שוט רחב של היצור מתמונת הייחוס A, שעולה לצד החומר מתמונת הייחוס B).

  • ה-slug נגזר מ-defaultName, באותיות קטנות, וכל רצף של תווים אחרים הופך ל-- אחד: השם Old Town הופך ל-old-town. אין שדה slug שצריך להגדיר.
  • האינדקס רק מתאים את האזכור לייחוס. הוא אף פעם לא נכתב לפרומפט, והפלטפורמה ממספרת את הייחוסים בעצמה.
  • התפקידים של תמונות (manual ו-wired-image) הם object, person, face, clothes, background, style, pose ו-texture. יצורים מקבלים creature, anatomy, markings, pose, color ו-style. אובייקטים מקבלים object, shape, material, color, texture ו-style. כל מילה בודדת אחרת עוברת כמו שנכתבה. בלי תפקיד, חל ה-defaultRole של הרשומה.
  • ~lock ו-~nolock אחרי אזכור, כמו ב-@town:1:background~lock, מפעילים או מכבים את נעילת הזהות של הייחוס הזה, רק באזכור הזה.
  • השמות מותאמים לייחוסים בסדר הזה: דמות, מיקום, תמונה, יצור, אובייקט. שם שמשותף לדמות ולתמונה מתייחס לדמות, ובתוך סוג אחד ההתאמה הראשונה גוברת.
  • אי אפשר להזכיר שם שה-slug שלו מתחיל בספרה, למשל 3D Render, שהופך ל-3d-render. כדי להזכיר ייחוס כזה, שנו את השם שלו. אזכור של ייחוס שחרג מהמגבלה של המודל נשאר טקסט מילולי.
  • אזכור מזיז את הייחוס מהרשימה שבסוף למקום שבו הקלדתם אותו, והאותיות של הייחוסים שאחריו משתנות לפי הסדר במשפט. ביצור או באובייקט, אזכור גם מחליף את השורה שהייחוס היה מוסיף אחרת בסוף.

נעילת ייחוסים

השדה referenceLock ב-POST /v1/generate-image מוסיף לפני תיאור הסצנה את הניסוח הבדוק של Nodaro לנאמנות לייחוסים:

ערךמה הוא מוסיףלמה הוא מתאים
standardהוראות להשתמש רק במה שהייחוסים מראים, לשמור על הדמיון ולשלב את הייחוסים יחדקומפוזיציות מכמה ייחוסים
multi-personאותו דבר, ועוד כללים שאוסרים לשנות פנים או לערבב ביניהןשני פרצופים או יותר בשוט אחד

שולחים את המזהה, לא טקסט: הניסוח שייך לפלטפורמה ומשתפר בלי לעדכן את הלקוח. בלי השדה, לא מתווספת נעילה.

הכוונה קולנועית לפי מזהה

השדה direction מתאר את המצלמה, את התאורה ואת המראה בעזרת מזהי בוררים, במקום טקסט חופשי. הנתיבים POST /v1/generate-image, POST /v1/generate-video ו-POST /v1/text-to-video מקבלים אותו. Nodaro כותב לפרומפט את הניסוח הבדוק שלו לכל מזהה, כך שבקשה שמורה מקבלת עם הזמן ניסוח משופר, במקום להקפיא את הטקסט שהלקוח שלכם כתב.

{
  "prompt": "a knight on a hill",
  "provider": "nano-banana-pro",
  "direction": {
    "shotSize": "wide-shot",
    "lens": "wide-24mm",
    "lightingStyle": "rembrandt",
    "style": "anime",
    "mood": ["happy", "joyful"]
  }
}

המפתחות ומאיפה מגיעים המזהים שלהם

כל מפתח הוא שדה של אחד הבוררים בבקרות יצירתיות. את המזהים התקפים מקבלים מ-GET /v1/picker-catalogs/<picker>, אותם קטלוגים שהבוררים בעורך משתמשים בהם.

מפתחותבוררתמונהוידאו
shotSize, angle, coverage, composition, vantageמסגורכןכן
poseתנוחהכןכן
compositionEffectאפקטי קומפוזיציהכןכן
cameraFormatמצלמה / סרט צילוםכןכן
lensעדשהכןכן
aperture, shutterSpeed, isoValueהגדרות חשיפהכןלא
timeOfDay, lightingStyle, lightingDirection, lightingRatio, colorTemperatureתאורהכןכן
colorLookצבע / מראהכןכן
atmosphereאווירהכןכן
postProcessאפקטי פוסט־עיבודכןלא
styleסגנוןכןכן
moodמצב־רוחכןכן
aestheticאסתטיקהכןכן
photoGenreז׳אנר צילוםכןלא
photographerצלםכןלא
renderQualityאיכות רינדורכןלא
settingסביבהכןכן
eraתקופהכןכן
backdropרקעכןכן
cameraMotionתנועת מצלמהלאכן
actionFxאפקטי פעולהלאכן
temporalSpeed, temporalFreeze, temporalDirection, temporalShutterזמןלאכן
transitionמעברלאכן
loopSubjectנושא לולאהלאכן

מפתח שלא רלוונטי לנתיב מתקבל ופשוט לא מוסיף כלום, כך שאפשר לשלוח את אותה מפה של מזהי מראה גם לנתיבי התמונה וגם לנתיבי הווידאו, בלי שינוי.

ערכים ומגבלות

  • מזהה אחד או רשימה. המפתחות עם בחירה מרובה, mood, aesthetic, photographer, atmosphere, postProcess, composition ו-lightingStyle, מקבלים מזהים עד המגבלה של כל מפתח, ומזהים עודפים נשמטים. מפתח של בחירה יחידה שמקבל רשימה משתמש ברשומה הראשונה.
  • שני מקרים נדחים עם 400 validation_error: יותר מ-8 רשומות למפתח אחד, ומזהה ארוך מ-100 תווים.
  • מפתח חסר הוא לא מפתח ריק. מפתח חסר פירושו שאין רמז, ואף פעם לא ברירת מחדל. מחרוזת ריקה או רשימה ריקה לא מוסיפות כלום.
  • הפלטות והמודבורדים שלכם אף פעם לא מדולגים. ב-/v1/generate-image, השדה colorLook מקבל גם "palette:<id>", והשדה style מקבל "moodboard:<id>". ראו את הסעיף הפלטות והמודבורדים שלכם.
  • מפתחות לא מוכרים ומזהים לא מוכרים מדולגים, ולא נדחים. לקוח חדש יותר מול שרת ישן יותר מקבל פחות רמזים, ולא שגיאה, ולכן עדכנו את השרת לפני לקוח ששולח מפתחות חדשים.
  • חבילות קטלוג מותאמות אישית. בפריסה שרושמת חבילות קטלוג משלה, הנתיב GET /v1/picker-catalogs מחזיר את המזהים שחבילה מוסיפה. המזהים האלה מתקבלים, אבל לא מוסיפים ניסוח ל-direction.

לאן המילים נכנסות

הביטויים מתווספים אחרי הפרומפט שלכם, במקטע [style]. שורת הצילום כוללת את cameraFormat, colorLook, style ו-era, ושורת הסצנה כוללת את שאר מפתחות המראה:

a knight on a hill

[style]:
<film line>
<scene line>
  • הסדר בתוך שורה הוא הסדר הקבוע של הפלטפורמה, לא הסדר של המפתחות שלכם. ביטוי ששני מפתחות מוסיפים נכתב פעם אחת.
  • שורה ריקה מושמטת. כשאף מפתח לא מוסיף כלום, אין מקטע בכלל, וה-prompt שלכם מגיע למודל בלי שינוי.
  • בנתיבי הווידאו, מפתחות התנועה עובדים אחרת. הם מוסיפים מונח מקצועי קצר, כגון cross-dissolve, ונשארים בגוף הפרומפט, אחרי הטקסט שלכם, כי התנועה היא חלק מהשוט. המפתח cameraMotion בא ראשון. רק מפתחות המראה נכנסים למקטע [style].
  • בנתיבי הווידאו, המפתח style מוסיף את הניסוח של הסגנון לווידאו במקום הניסוח שלו לתמונה, באותו מקטע [style]. הניסוח לווידאו נכתב לשוטים בתנועה: הוא מציין קודם את המדיום ואחר כך את הטכניקות שלו, וסגנון צילומי מציין מדיום של צילום חי, כך שהתוצאה נשארת מצולמת. לכן אותו "style": "anime" מוסיף ניסוח שונה בנתיב וידאו וב-generate-image. השדה jobs.input_data.prompt שומר את הטקסט שהמודל קיבל. נקודות הקצה של הקטלוג מחזירות רק את הניסוח לתמונה. על הקנבס זה עובד באותו אופן: ראו את הסעיף סגנונות לתמונות ולווידאו בדף סגנון.

כשהפרומפט ארוך מדי

כל מודל מקבל פרומפט עד אורך משלו. אובייקט direction מלא יכול לחרוג לבדו ממגבלה קטנה, למשל 3,000 תווים ב-Seedream בצד התמונה, ו-1,000 תווים ב-Kling בצד הווידאו. במקרה כזה, Nodaro מסיר את ביטויי ההכוונה אחד אחד, מסוף הסדר הקבוע שלו, עד שהפרומפט נכנס במגבלה. שום דבר אחר לא מוסר לפניהם:

  • ביטויי הנושא מוסרים רק אחרי כל ביטויי ההכוונה.
  • הטקסט שלכם, הייחוסים שלכם והביטויים שקושרים אותם, אזכורי @ והשורות Style: ו-Avoid: תמיד נשארים.
  • רק כשהפרומפט עדיין לא נכנס, גם בלי שום רמז, סוף הטקסט נחתך ומתווסף ....

בנתיבי הווידאו, התקציב סופר גם את הוראות הייחוס שהנתיב מוסיף, ואלה אף פעם לא מוסרות. במודל שאין לו הגדרה של פרומפט שלילי, ה-negativePrompt שלכם מתווסף כשורת Avoid: שהמקום שלה נשמר קודם, כך שפרומפט שלילי ארוך בא על חשבון ביטויי הרמזים, ולא על חשבון הטקסט שכתבתם. הטקסט האופציונלי injectCharacterContext מתווסף אחרי השלב הזה ולא נכלל בתקציב.

המשימה מתעדת מה קרה. השדה input_data.prompt הוא מה שהמודל קיבל, השדה input_data.userPrompt הוא הטקסט ששלחתם (מחרוזת ריקה כששלחתם רק direction), והשדה input_data.direction הוא המזהים שלכם כפי ששלחתם אותם.

הכוונה ששמורה ברכיב

רכיב יצירת תמונה בתהליך שמור יכול לשמור בנתונים שלו את אותו אובייקט direction. את האובייקט כותבים ה-API, MCP או אפליקציה שיוצרת תהליכים. העורך מתחשב בו בכל הרצה ובתצוגת הפרומפט הסופי. מזהים שמורים מתווספים לכל בורר מסגור, תאורה או סגנון שמחובר לרכיב: הרמז מהבורר המחובר בא קודם, ואחריו המזהים השמורים. ערכות וייצואים של תהליכים שומרים את המזהים יחד עם שאר הרכיב.

הפלטות והמודבורדים שלכם

פלטה היא סט משלכם של 2–12 צבעים, ומודבורד הוא סט משלכם של 1–12 תמונות ייחוס עם תיאור. שומרים אותם פעם אחת, ואז מכוונים בעזרתם כל הרצה של POST /v1/generate-image, כמו שבוחרים מראה צבע מובנה או סגנון מובנה. הם עובדים בכל מהדורה. מה הם עושים בעורך מוסבר במדריך פלטות ומודבורדים.

פלטהמודבורד
תוכןשם באורך 1–80 תווים, 2–12 צבעים בפורמט #RRGGBB והערה אופציונלית של עד 500 תוויםשם, תיאור אופציונלי של עד 1,000 תווים ובין 1 ל-12 תמונות { url, caption? }
אופן השימושdirection.colorLook: "palette:<id>"direction.style: "moodboard:<id>"
מה ההרצה מקבלתכל צבע בפרומפט, בשם יומיומי ובקוד ההקסדצימלי שלוהתיאור בפרומפט, והתמונות כייחוסי סגנון
{
  "prompt": "a lighthouse on a cliff at dusk",
  "provider": "nano-banana-pro",
  "referenceImageUrls": ["https://example.com/my-lighthouse.png"],
  "direction": {
    "colorLook": "palette:0f9e8d7c-6b5a-4c3d-9e2f-1a2b3c4d5e6f",
    "style": "moodboard:1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "lightingStyle": "rembrandt"
  }
}

ניהול פלטות ומודבורדים

שיטהנתיבגוף הבקשה או פרמטרי השאילתהמה היא עושה
GET/v1/paletteslimit (1–100, ברירת המחדל 50), cursorהפלטות שלכם, מהחדש לישן: { data, nextCursor }.
POST/v1/palettes{ name, colors, description? }יצירת פלטה. מחזירה 201. הצבעים נשמרים באותיות גדולות.
GET/v1/palettes/:idאיןפלטה אחת.
PATCH/v1/palettes/:idכל שילוב של name, colors ו-descriptionרק השדות ששולחים נכתבים. הערך description: null מנקה את ההערה.
DELETE/v1/palettes/:idאיןמחזירה { success: true }.
GET/v1/moodboardslimit, cursorהמודבורדים שלכם, מהחדש לישן: { data, nextCursor }.
POST/v1/moodboards{ name, description?, images }יצירת מודבורד. מחזירה 201.
GET/v1/moodboards/:idאיןמודבורד אחד.
PATCH/v1/moodboards/:idכל שילוב של name, description ו-imagesרק השדות ששולחים נכתבים. השדה images מחליף את כל התמונות.
DELETE/v1/moodboards/:idאיןמחזירה { success: true }. התמונות המקושרות לא משתנות.
  • התמונות של מודבורד הן קישורים, אף פעם לא עותקים. כל url הוא כתובת http או https שהיא לא localhost ולא כתובת ברשת פרטית, עד 2,048 תווים. כיתוב יכול להכיל עד 200 תווים. תמונה שמחקתם, או תמונה שנמחקה לפי מדיניות שמירת המדיה של התוכנית שלכם, נעלמת גם מהמודבורד.
  • nextCursor הוא ערך אטום. העבירו אותו בחזרה כ-cursor כדי לקבל את העמוד הבא. בעמוד האחרון הוא null.
  • הם שלכם בלבד. על פלטה או מודבורד של אדם אחר התגובה היא 404, כמו על פלטה או מודבורד שלא קיימים.
  • הרשאות: אסימון של אפליקציית OAuth צריך assets:read לקריאות ו-assets:write לכתיבות. מגבלת הכתיבות היא 30 לדקה.
  • אותם נתיבים זמינים ב-SDK (client.palettes, client.moodboards), ב-CLI (nodaro palettes, nodaro moodboards) ובכלי ה-MCP list_palettes, save_palette, list_moodboards ו-save_moodboard. כלי ה-MCP generate_image מקבל palette_id ו-moodboard_id. דרך MCP אין מחיקה.

מה ההרצה מקבלת

  • פלטה מוסיפה color palette: <name> <hex>, … לשורת הצילום במקטע [style], במקום שבו היה נכנס מראה הצבע המובנה. כל צבע מקבל את השם היומיומי הקרוב אליו, כי מודל נצמד בצורה אמינה יותר לצבע שיש לו שם, ואת קוד ההקסדצימלי המדויק שלו. ההערה של הפלטה לא מתווספת לפרומפט.
  • מודבורד מוסיף את התיאור שלו, בשורה אחת, במקום שבו היה נכנס הסגנון המובנה. כשאין לו תיאור, נשלחות רק התמונות שלו.
  • כמו כל ביטוי הכוונה, הביטויים האלה מוסרים ראשונים כשהפרומפט חורג מהמגבלה של המודל.
  • התמונות של המודבורד נשלחות למודל כתמונות ייחוס, כל אחת עם שורה קצרה שאומרת למודל לקחת ממנה את הצבעים, את האור, את המרקם ואת האווירה, ולא את הנושא או את הקומפוזיציה שלה. כשיש לתמונה כיתוב, הוא מתווסף.
  • הייחוסים שלכם באים קודם. תמונות ששולחים בעצמכם שומרות על המקומות ועל המספור שלהן. התמונות של המודבורד ממלאות רק את המקומות שנשארים אחריהן.
  • אף פעם לא יותר ממה שהמודל מקבל. התמונות נכנסות לפי הסדר במודבורד, ומה שלא נכנס לא נשלח. במקרה כזה התגובה כוללת את האזהרה moodboard_images_not_sent. מודל שלא מקבל תמונות ייחוס לא מקבל אף אחת מהן, והתיאור עדיין נכנס.
  • מחיר. התמונות נחשבות לייחוסים, ולכן ההרצה מתומחרת כמו כל הרצה עם אותו מספר ייחוסים. המחיר שנבדק לפני ההרצה והמחיר שמשוריין סופרים את אותן תמונות: אלה שנשלחו בפועל.
  • aspectRatio: "auto" שומר על הצורה של התמונה הראשונה שההרצה שולחת. כשלא שולחים תמונה משלכם, זו התמונה הראשונה של המודבורד.
  • המשימה שומרת את המזהים, לא עותקים. הרצה חוזרת של המשימה משתמשת בפלטה או במודבורד כפי שהם באותו רגע.

שגיאות ומגבלות

סטטוסקודמתי
400validation_errorקידומת palette: או moodboard: בלי uuid אחריה, פלטה במפתח שהוא לא colorLook, מודבורד במפתח שהוא לא style, פלטה או מודבורד ששולבו עם ערך אחר באותו מפתח, או בקשה ששולחת גם presetId. השדה field מציין את המפתח.
404direction_not_foundהפלטה או המודבורד לא שייכים לכם, או שהם כבר לא קיימים. השדה field הוא direction.colorLook או direction.style.

שתי התגובות מגיעות לפני שמשהו נוצר ולפני שנגבים קרדיטים. פלטות ומודבורדים עובדים רק ב-generate-image: הנתיבים POST /v1/generate-video ו-POST /v1/text-to-video מחזירים עליהם 400 validation_error. בתהליך שמור, כשה-direction של רכיב יצירת תמונה מציין פלטה או מודבורד, הם נטענים מחדש בכל פעם שהתהליך רץ.

תיאור הנושא לפי מזהה

השדה subject הוא אותו רעיון, בשביל מי שמופיע בשוט: האדם, הסטיילינג שלו והאביזרים בפריים. הנתיבים POST /v1/generate-image, POST /v1/generate-video, POST /v1/text-to-video, POST /v1/generate-character ו-POST /v1/generate-creature מקבלים אותו:

{
  "prompt": "on the seawall at dusk",
  "provider": "nano-banana-pro",
  "subject": {
    "type": "woman",
    "age": "age-30s",
    "ethnicity": "east-asian",
    "hairBase": "base-short-straight",
    "makeup": "makeup-smoky",
    "outerwear": "outerwear-trench",
    "heldProp": "smartphone"
  }
}
  • המפתחות הם השדות של הבוררים אדם וסטיילינג, כגון type, age, ethnicity, faceShape, hairColor, skinTone, makeup, outfit, outerwear ו-footwear, ועוד שלושה מפתחות של אביזרים: heldProp (אביזר יד), material (חומר) ו-animal (חיה). הנתיבים GET /v1/picker-catalogs/person ו-/styling מחזירים כל שדה וכל מזהה.
  • subject ו-direction אף פעם לא חופפים. המפתחות שלהם נפרדים, כך שבחירה אחת אף פעם לא מוסיפה שני ביטויים. המפתח pose שייך ל-direction.
  • customAge הוא המספר היחיד. שלחו "age": "age-custom" עם "customAge": 34 כדי לקבל גיל מדויק בשנים. הערך מעוגל ונשמר בטווח שבין 0 ל-120.
  • לרשימות יש מגבלות לכל מפתח. המפתחות jewelry, wardrobeState ו-distinctiveFeature מקבלים 3 מזהים. המפתחות ethnicity, regionalAesthetic, hairColor, eyeColor, lipState, eyeState, skinTexture, hairState, heldProp ו-material מקבלים 2. כל מפתח אחר, כולל animal, מקבל 1. מזהים עודפים נשמטים.
  • חריגות שנדחות: יותר מ-8 רשומות למפתח אחד, מזהה ארוך מ-100 תווים, יותר מ-128 מפתחות או מפתח ארוך מ-64 תווים. התגובה היא 400 validation_error.
  • מפתחות לא מוכרים מוסרים, ומזהים לא מוכרים מדולגים. השדה input_data.subject במשימה מתעד בדיוק את המזהים שהיו בשימוש.
  • ביטויי הנושא הם חלק מהטקסט שלכם, לפני ביטויי ההכוונה, ואף פעם לא במקטע [style]. הבורר אדם הופך לביטוי אחד, והבורר סטיילינג לביטוי אחר, ובחירות חופפות נכתבות פעם אחת. בנתיב התמונה, כל בחירה מוסיפה את הביטוי המלא שלה; נתיבי הווידאו מוסיפים את המונח הקצר, כי פריים הפתיחה כבר מראה מי הנושא.
  • ב-POST /v1/generate-character וב-POST /v1/generate-creature, השדה subject מתאר מי מופיע בפורטרט. הניסוח נכנס מיד אחרי seedPrompt או description, ואחרי בחירות האדם והמלתחה של הדמות או של היצור עצמם, ובחירה שמופיעה בשניהם באותו ניסוח נכתבת פעם אחת. שני הנתיבים האלה משתמשים בניסוח של תמונת סטילס, ואף פעם לא מקצרים את הביטויים. ראו בדף ה-API דמויות.

סשני יצירה

כלי יצירה שבנוי על ה-API, כגון כלי ליצירת תמונות, וידאו או מוזיקה, יכול לשמור את העבודה שלו בסשנים בתוך הפרויקטים שלכם: בפרויקט נמצאים סשנים, ובכל סשן נמצאים פריטים. אותם סשנים מוצגים בכל מכשיר, והאפליקציה שלכם לא צריכה לשמור שום דבר בעצמה.

# 1. Open a session, optionally inside one of your projects.
SESSION=$(curl -s -X POST "https://app.nodaro.ai/v1/sessions" \
  -H "Authorization: Bearer $NODARO_API_KEY" -H "Content-Type: application/json" \
  -d '{"projectId": "<project-id>", "tool": "create-image", "title": "Beach"}' | jq -r .data.id)

# 2. Generate inside it: send sessionId beside the usual settings.
curl -s -X POST "https://app.nodaro.ai/v1/generate-image" \
  -H "Authorization: Bearer $NODARO_API_KEY" -H "Content-Type: application/json" \
  -d "{\"prompt\": \"a red car\", \"sessionId\": \"$SESSION\", \"origin\": \"create-image\"}"

# 3. Read the session's feed, newest first.
curl -s "https://app.nodaro.ai/v1/sessions/$SESSION/items" -H "Authorization: Bearer $NODARO_API_KEY"
שיטהנתיבמה היא עושה
POST/v1/sessionsיצירת סשן. גוף הבקשה: tool (נדרש: אותיות לטיניות קטנות, ספרות ומקפים, עד 40 תווים), projectId (אופציונלי, אחד הפרויקטים שלכם) ו-title (אופציונלי, עד 200 תווים).
GET/v1/sessionsהסשנים שלכם, מהחדש לישן. פרמטרי שאילתה: projectId (none לסשנים שלא שייכים לאף פרויקט), tool, includeArchived=true, limit (1–100, ברירת המחדל 50) ו-cursor. בכל סשן מופיעים itemCount (הפריטים הפעילים שלו), removedCount (הפריטים שלו בפח), coverJobId ועד ארבע כתובות ב-previewUrls: קודם התמונה של תמונת השער, כשהיא מוגדרת, ואחר כך התמונות של הפריטים החדשים ביותר שהסתיימו.
GET/v1/sessions/:idסשן אחד.
PATCH/v1/sessions/:idשינוי של title (null פירושו ללא שם), של archived ושל coverJobId: אחד הפריטים של הסשן, שיופיע ראשון בתצוגות המקדימות שלו (404 כשהוא לא פריט של הסשן הזה), או null כדי לחזור לבחירה אוטומטית. הפרויקט של סשן נקבע כשהסשן נוצר.
DELETE/v1/sessions/:idמחיקת הסשן והקישורים שלו. המשימות שלו נשמרות, ונשארות בכל סשן אחר שהן נמצאות בו.
GET/v1/sessions/:id/itemsהפיד: כל פריט פעיל, שנוצר בסשן או שיובא אליו, מהחדש לישן. עם removed=true, במקום זאת, הפריטים שהוסרו ממנו, שהם החלק שלו בפח, מההסרה האחרונה לראשונה. לכל פריט יש jobId, addedAt, removedAt (null כשהפריט פעיל), imported, importedFrom { sessionId, title } ו-job במבנה ש-GET /v1/jobs/:id מחזיר. פריט שמחקתם את המשימה שלו לא מופיע באף אחת מהרשימות. עוברים בין העמודים עם limit ו-cursor.
POST/v1/sessions/:id/itemsייבוא של { "jobIds": [...] }, 1–100 משימות, כקישורים, אף פעם לא כעותקים. כשמזהה כלשהו הוא לא אחת המשימות שלכם, או שהמשימה נמחקה, שום דבר לא מיובא (404). פריט שהוסר מהסשן חוזר למקום שבו היה. מחזירה { imported, requested }.
DELETE/v1/sessions/:id/items/:jobIdהסרה של פריט אחד מהסשן הזה. הפריט עובר לפח ונשאר שם עד שמשחזרים אותו או מוחקים אותו לצמיתות. שום דבר לא מתנקה אוטומטית. רק הקישור זז: המשימה, וכל סשן אחר שהיא נמצאת בו, נשארים. הפרמטר ?forever=true מוחק לצמיתות פריט שכבר הוסר, והמשימה עדיין נשארת. בפריט פעיל, הנתיב מחזיר 409 not_in_trash.
POST/v1/sessions/:id/items/:jobId/restoreהחזרה של פריט שהוסר, למקום שבו היה.
POST/v1/sessions/:id/items/moveהעברה של { "jobIds": [...], "fromSessionId": "…" }, 1–100 פריטים, לסשן הזה, בטרנזקציה אחת. הסשן הזה מקבל אותם, וסשן המקור שומר אותם כפריטים שהוסרו, כך שאפשר לבטל את ההעברה מהפח של סשן המקור. כשמזהה כלשהו הוא לא פריט פעיל של fromSessionId, שום דבר לא זז (404). מחזירה { moved }.
  • כל נתיב שיוצר משימה מקבל sessionId, כגון generate-image, generate-video, text-to-video, text-to-speech ו-generate-music. הערך חייב להיות אחד הסשנים שלכם, באותו צד של הגבול בין סביבות העבודה כמו הבקשה. אחרת התגובה היא 404, ושום דבר לא נוצר ולא נגבים קרדיטים. הרצות של תהליך אף פעם לא נשמרות בסשן.
  • ה-session_id של המשימה נקבע פעם אחת, כשהמשימה נוצרת. הוא מופיע ב-GET /v1/jobs/:id וב-GET /v1/jobs.
  • כל נתיב שיוצר משימה מקבל גם origin, ה-slug של האפליקציה שלכם. המשימה שומרת אותו ב-input_data.origin, והנתיב GET /v1/jobs?origin= מסנן לפיו. ערך שהוא לא slug נדחה עם 400 validation_error, ושום דבר לא נוצר ולא נגבים קרדיטים.
  • כדי להעביר עבודה לפרויקט אחר, העבירו את הפריטים לסשן של אותו פרויקט עם POST /v1/sessions/:id/items/move. הפרויקט של סשן קבוע, ולכן כך פריט עובר לפרויקט אחר. כדי להשאיר פריט בשני הפרויקטים, ייבאו אותו במקום להעביר אותו.
  • איפה משימה נמצאת עכשיו. הנתיב GET /v1/jobs מקבל projectId=<id>, המשימות שנמצאות עכשיו בסשן של אותו פרויקט, ו-projectId=none, המשימות שנמצאות בסשן שלא שייך לאף פרויקט. הוא מקבל גם inSession=false, המשימות שלא נמצאות עכשיו באף סשן (כללי), ו-inSession=true. כל משימה מופיעה פעם אחת, לא משנה בכמה סשנים היא נמצאת. הפרמטר withSessions=true מוסיף לכל משימה sessions: [{ id, title, projectId }], לתצוגה של ״כל מה שבפרויקט הזה״. אי אפשר לשלב את projectId עם inSession=false (400). המסננים האלה משתלבים עם type, עם status ועם שאר המסננים.
  • הפח. פריטים שהוסרו ומשימות שנמחקו עוברים לפח. ראו בדף ה-API הפח.
  • הרשאות: עם אסימון של אפליקציית OAuth, קריאת סשנים דורשת jobs:read. יצירה, עריכה, ייבוא והסרה דורשים assets:write, וכך גם שליחת sessionId עם יצירה. אסימון API אישי שמוגבל לתהליכים מסוימים לא יכול להגיע לנתיבים האלה.

אומדני מחיר להרצה

הנתיב POST /v1/quote מחזיר כמה קרדיטים ישוריינו להרצת רכיב, לפני שמתחילים אותה. שלחו את סוג הרכיב ובדיוק את גוף הבקשה שהייתם שולחים לנתיב ההרצה שלו. השרת מתמחר אותו עם הקוד של נתיב ההרצה עצמו: אותה בדיקה של גוף הבקשה, אותה מדידה של קליפי ייחוס, אותו מזהה קרדיטים ואותו חישוב. לכן אומדן המחיר הוא בדיוק הסכום שמשוריין להרצה. שום דבר לא מתחיל, ולא נגבים קרדיטים.

  • איפה: רק ב-Nodaro Cloud. הנתיב דורש אימות ומאפשר 30 בקשות לדקה.
  • אילו סוגים: text-to-video, generate-video, video-to-video ו-video-upscale. ההשלמה ב-1080p של טיוטת Seedance 2.5 ב-video-upscale מתומחרת לפי הטיוטה ולפי הקליפים שהיא נוצרה מהם. בקשה עם כל סוג אחר נדחית עם 400 quote_unsupported, עם רשימת הסוגים הנתמכים.
  • עריכות Seedance: עריכת Seedance ב-video-to-video מתומחרת עם כל קליפ שנשלח איתה, ב-videoUrl וב-referenceVideoUrls. ראו את הדף וידאו לווידאו לרשימות הייחוסים.
  • SDK: client.nodes.quote(type, params).
{
  "type": "text-to-video",
  "params": {
    "prompt": "edit {video:1} as follows: make it black and white",
    "provider": "seedance-2-5",
    "duration": -1,
    "aspectRatio": "adaptive",
    "referenceVideoUrls": ["https://…/clip.mp4"]
  }
}

התגובה היא { "data": { identifier, reserve, expected?, adjustments, warnings } }:

שדהמשמעות
identifierמזהה הקרדיטים שההרצה מחויבת לפיו.
reserveהקרדיטים שמשוריינים להרצה כשהיא מתחילה.
expectedהקרדיטים שההרצה אמורה לעלות בפועל, כשהקלטים שנמדדו מאפשרים לחשב את זה. הרצת Seedance עם סרטון ייחוס משוריינת לפי המקרה הגרוע ביותר: שניות הקלט ועוד הארוך מבין האורך המבוקש והקליפ הארוך ביותר. עם משך אוטומטי, כשכל הקליפים נמדדו, השריון הוא שניות הקלט ועוד האורך של הקליפ הראשון, מעוגל כלפי מעלה לשנייה שלמה, ועוד שנייה אחת. השדה expected הוא הקלט ועוד האורך שההרצה כנראה תרנדר. זה האורך של קליפ המקור בעריכה עם משך אוטומטי, והשניות המבוקשות בכל מקרה אחר. הערך אף פעם לא גבוה מ-reserve.
adjustmentsרשימה של { code, message, credits? } שמסבירה למה המחיר הוא מה שהוא: ref_video_length (תמחור לפי האורכים של הקליפים), extra_reference_images (תמונות ב-MiniMax H3 מעבר ל-5 הראשונות), auto_duration, loop_trim_addon ו-voiced_audio_addon (עם הקרדיטים שלהם), ו-params_adjusted (רזולוציה או יחס שהותאמו לאלה שהמודל מציע).
warningsרשימה של { code, message }: settles_to_actual (ההרצה מחויבת לפי מה שנוצר, והקרדיטים מ-reserve שלא נדרשו מוחזרים) ו-ref_video_unmeasured (לא היה אפשר למדוד קליפ, ולכן הוא מתומחר כקליפ הארוך ביותר שהמודל מקבל).
  • גוף בקשה לא תקין נדחה עם ה-400 של נתיב ההרצה עצמו. קליפ שההרצה הייתה דוחה נדחה עם ה-400 video_too_long שלה. מודל שהפריסה הזו לא מציעה נדחה עם ה-403 model_not_available של ההרצה.
  • המדידה של קליפ שמאוחסן ב-Nodaro, כגון העלאה או תוצאה שנוצרה, נשמרת ל-15 דקות. כשמבקשים אומדן מחיר ואז מריצים את אותו גוף בקשה, הקליפ נמדד פעם אחת.
  • אומדן מחיר בודק את גוף הבקשה ואת המחיר, לא את היתרה או את התוכנית שלכם. ההרצה עדיין יכולה להידחות עם 402. כמה בדיקות שרק ההרצה עושה עדיין יכולות לדחות גוף בקשה שקיבל אומדן, למשל מודל שצריך פריים פתיחה.

גילוי רכיבים

הנתיב GET /v1/nodes מחזיר את כל סוגי הרכיבים שהשרת מכיר, והנתיב GET /v1/nodes/:type מחזיר סוג אחד. שני הנתיבים ציבוריים, לא צריכים אסימון ונשמרים במטמון ל-5 דקות. על סוג לא מוכר התגובה היא 404 not_found.

curl -s https://app.nodaro.ai/v1/nodes/generate-image | jq .data
const { data: nodes } = await client.nodes.list()
const imageNodes = nodes.filter((n) => n.category === 'ai-image')

const { data: generateImage } = await client.nodes.get('generate-image')
console.log(generateImage.providers)
nodaro nodes list --category ai-image
nodaro nodes get generate-image
{
  "data": {
    "type": "generate-image",
    "label": "Generate Image",
    "category": "ai-image",
    "description": "Generate an image from a text prompt using an AI provider.",
    "outputType": "image",
    "creditCost": "3-682",
    "providers": ["nano-banana-pro", "gpt-image-2", "gpt-image-2-5-flare", "seedream-5-pro", "z-image"],
    "capabilities": ["supports-reference-image", "supports-aspect-ratio"],
    "inputSchema": {
      "fields": [
        { "key": "prompt", "type": "text", "required": true },
        { "key": "provider", "type": "select", "options": ["nano-banana-pro", "gpt-image-2"] },
        { "key": "aspectRatio", "type": "select" },
        { "key": "promptPrefix", "type": "text" },
        { "key": "promptSuffix", "type": "text" }
      ]
    }
  }
}
שדהמשמעות
typeסוג הרכיב. ברוב סוגי הרכיבים הוא גם הנתיב: POST /v1/<type>.
label, category, descriptionאיך העורך קורא לרכיב ובאיזו קבוצה הוא מציג אותו.
outputTypetext, image, video, audio, data או none.
creditCostעלות הקרדיטים של הרכיב, או הטווח שלה. זה המחיר שהרצה עולה, אותו מספר שמופיע בכפתור הרצה של הרכיב. ברכיבים קיצוץ וידאו, לולאת וידאו ושילוב סרטונים, זה במקום זאת המחיר של מדרגה אחת של 5 שניות, והרצה עולה כמה מדרגות. רק ב-Nodaro Cloud: מהדורות בלי קרדיטים משמיטות את השדה.
estimateהערך true כש-creditCost הוא אומדן: הקריאה הטיפוסית של רכיב LLM עם חיוב לפי השימוש, במודל ברירת המחדל שלו. ההרצה מחויבת לפי השימוש בפועל, ולכן הציגו את המספר כ-≈N. רכיב בחירת המיטב מציג טווח "0-N" שמסומן estimate: מהאסטרטגיות החינמיות שלו ועד הקריאה הטיפוסית של שופט ה-AI שלו. השדה חסר כשהמחיר קבוע. רכיב LLM עם חיוב לפי השימוש, שלמודל ברירת המחדל שלו עדיין אין מחיר, מציג creditCost: "unpriced", והרצה במודל הזה נדחית. ראו בדף ה-API שגיאות.
creditRateלרכיב שהמחיר שלו נקבע לפי יחידה של מדד משלו, וה-creditCost שלו הוא מילה ולא מספר. כרגע זה רכיב מסגרות דוברים, עם creditCost שערכו "per-1000-frames". האובייקט הוא { identifier, unit, creditsPerUnit, minUnits, rounding, note }. השדה creditsPerUnit הוא המחיר המדויק של יחידה אחת, בלי עיגול. עם rounding: "ceil-run-total", הרצה של N יחידות (לפחות minUnits) עולה ceil(N × creditsPerUnit), עם עיגול כלפי מעלה פעם אחת. אל תכפילו את המחיר של יחידה אחת מ-/v1/credits/model-cost.
providersמזהי המודלים שהרכיב מקבל ב-provider.
capabilitiesדגלי יכולות, כגון supports-reference-image.
inputSchema.fieldsההגדרות של הרכיב, עם הסוג שלהן, אם הן נדרשות, והאפשרויות שלהן.

כל רכיב שמקבל פרומפט מציג גם promptPrefix ו-promptSuffix: טקסט שמתווסף לפני הפרומפט ואחריו. ראו את הדף טקסט לפני ואחרי הפרומפט. ברכיבים עם מגבלות לפי מודל יש שדות נוספים:

שדהמשמעות
maxDurationSecמשך הזמן הארוך ביותר שהרכיב מקבל.
sparseProvidersמודלים עם מעט אורכי מקטע בלבד. ערך שנמצא ביניהם מותאם לקרוב ביותר.
providerResolutionsהרזולוציות של כל מודל, למשל { "minimax-h3": ["2K", "768P"] }.
providerResolutionWireהערך המדויק שצריך לשלוח לכל רזולוציה, למשל 768P ולא 768p, לרמה הזולה יותר של MiniMax H3.
soundtrackברכיב יצירת וידאו Pro: השרת מקבל את הקלט soundtrack של האודיו המקורי.

אובייקט התיאור של הרכיב מתרחב עם הזמן, ולכן התעלמו משדות שאתם לא מכירים. אותם נתונים מזינים את מדריך הרכיבים.

גילוי מודלים

הנתיב GET /v1/models מחזיר את קטלוג המודלים, מקובץ לפי סוג ולפי יצרן. הנתיב ציבורי ונשמר במטמון ל-5 דקות, והנתונים שלו זהים לאלה שכלי ה-MCP list_models מחזיר.

מודל שהפריסה הזו לא מציעה לא מופיע ברשימה, כולל מודל שמנהל כיבה. אותו מתג דוחה הרצה של המודל הזה עם 403 model_not_available. לקוח ששומר את הרשימה במשך 5 הדקות עדיין עשוי לבקש מודל כזה.

curl -s "https://app.nodaro.ai/v1/models?kind=video&mode=i2v" | jq '.totalModels'
const catalog = await client.models.list({ kind: 'video', mode: 'i2v' })
for (const section of catalog.sections)
  for (const family of section.families)
    for (const m of family.models) console.log(m.id)
nodaro models list --kind video --mode i2v

התגובה היא { sections, recommendations, totalModels }. כל מודל מציין את היצרן שלו וכולל את הסמל של היצרן:

שדהסוגמשמעות
maker{ id, name }החברה שיצרה את המודל. השדה id יציב, אחד לכל חברה, באותיות קטנות עם מקפים, כגון google, black-forest-labs או bytedance. השתמשו בו כמפתח לקבצים ולמשאבים שלכם, וטפלו גם במזהה שאתם לא מכירים, כי שרת חדש יותר יכול להוסיף יצרנים. הוא לא תמיד ה-family שהמודל מקובץ תחתיה.
logoUrlstring או nullהסמל הרשמי של היצרן כקובץ SVG ב-CDN המדיה של השרת הזה, או null כשהשרת לא מפרסם סמל. במקרה כזה הציגו חלופה, כגון שם היצרן או האות הראשונה שלו. השתמשו בכתובת כמו שהיא: היא כוללת את הגרסה של הקובץ, כך שסמל שהוחלף מגיע בכתובת חדשה.

הנתיב GET /v1/model-makers מחזיר רק את היצרנים, לאפליקציה שמציגה סמלים ולא צריכה את הקטלוג. התגובה היא { makers: [{ id, name, logoUrl }] }, עם כל היצרנים שהפלטפורמה מכירה. השדות זהים לאלה שלמעלה, כך ששני הנתיבים אף פעם לא סותרים זה את זה. הנתיב ציבורי ונשמר במטמון ל-5 דקות, כמו GET /v1/models. הוא מציג יצרן גם כשאף אחד מהמודלים שלו לא מוצע.

כלי ה-MCP list_models כולל את maker, אבל לא את logoUrl.

כל מודל כולל גם את היכולות שלו (modes, features, aspectRatios, resolutions, durations), את מחירי הקרדיטים שלו לכל וריאנט ב-Nodaro Cloud ב-pricing, טיפים קצרים ב-promptTips, ואת doctrineCovered, שערכו true רק כשיש מדריך פרומפטים מבוסס מקורות למשפחת המודל. הקרדיטים ב-pricing הם המחיר שהרצה עולה, אותו מספר שמופיע בכפתור הרצה בעורך.

מודל דיבור, כגון מודל של טקסט לדיבור או מודל דיאלוג, מציג שורת pricing שנייה, <model>:per-100-chars, כשהדיבור מתומחר לפי אורך. השורה הזו היא המחיר של כל 100 תווים, או חלק מהם, מהטקסט שנשלח, עם מינימום של 8 יחידות להרצה. בקשה מתומחרת כמכלול ומעוגלת פעם אחת, ולכן N × the row's credits, כש-N = max(8, ceil(characters / 100)), הוא רק חסם עליון. המחיר המדויק הוא המזהה <model>:per-100-chars:<N>u, ש-POST /v1/credits/model-costs ו-GET /v1/credits/model-cost מחזירים. השתמשו במספר הזה כאומדן המחיר, ולא במכפלה. כשהשורה חסרה, גם כל המזהים מסוג :<N>u חסרים: השתמשו בשורה הקבועה של המודל. ראו בדף ה-API מחירים מדויקים להרצות שמתומחרות לפי יחידה.

פרמטר שאילתהערכיםמה נשאר ברשימה
kindimage, video או audioסוג מדיה אחד
modeלמשל t2i, i2v, t2v, tts, video-analysisפעולה אחת
familyיצרן, למשל Google או Bytedanceיצרן אחד
featuredOnlytrueמודלים נבחרים

דפי המודלים מציגים את אותו קטלוג.

גילוי ערכי בוררים

לבוררים של בקרות יצירתיות יש קטלוגים ציבוריים של מזהים תקפים, הערכים ש-direction ו-subject מקבלים:

שיטהנתיבמה היא מחזירה
GET/v1/picker-catalogsכל בורר: nodeType, label, kind, השדה או השדות שלו, optionCount ו-imageCount.
GET/v1/picker-catalogs/:nodeTypeהאפשרויות של בורר אחד. הפרמטר ?detail=full מוסיף לכל אפשרות את description ואת promptHint (באפשרות של style, הניסוח שלה לתמונה), הפרמטר ?category= מסנן בורר עם שדה יחיד, והפרמטר ?field= מחזיר שדה אחד של בורר עם כמה שדות.
GET/v1/catalogsכל הקטלוגים בקריאה אחת, לפי הבחירה של הפריסה. השדה data מופיע רק כשהפריסה רשמה חבילות קטלוג.
POST/v1/text-to-picker״מילוי ב-AI״: בחירת מזהים לבוררים רבים מתוך תיאור חופשי של סצנה. בלי llmModel, הנתיב מריץ את Gemini 3.8 Flash. החיוב הוא לפי הטוקנים שהקריאות שלו משתמשות בהם, בתעריף של המודל. ראו את הדף קטלוגי הבוררים.

בכל אפשרות יש id, label ו-term, הביטוי הקצר לשימוש בפרומפט, ועוד imageUrl כשיש לאפשרות תמונה. הקטלוגים מגיעים גם כנתונים בחבילת ה-npm @nodaro/prompts. המבנים המלאים מופיעים בדף קטלוגי הבוררים. מהטרמינל: הפקודות nodaro pickers list, nodaro pickers get mood --full ו-nodaro pickers analyze "<text>".

פלט מובנה מ-LLM

הנתיב POST /v1/llm/structured מריץ קריאה אחת למודל שפה, שהתשובה שלה נכפית לתוך JSON Schema שאתם מספקים, עוברת בדיקת תקינות ומוחזרת כאובייקט. הקריאה מחויבת לפי הטוקנים שהיא השתמשה בהם בפועל, בתעריף של המודל בשירות שהריץ אותה. הטוקנים כוללים את פרומפט המערכת, הקלט והסכמה שלכם, כל בקשה חוזרת אחרי בדיקת תקינות שנכשלה וכל מעבר לשירות גיבוי, ואת התשובה. ראו את הסעיף איך מחויבות קריאות LLM בדף קרדיטים.

  • לפני הקריאה, Nodaro משריין קרדיטים: המחיר של הניסיון הראשון לפי תקרת הפלט של המודל. כשהיתרה נמוכה מהשריון, הבקשה נדחית עם 402 וההודעה "Needs up to N credits" (נדרשים עד N קרדיטים).
  • אחרי הקריאה, החיוב הוא לפי השימוש בפועל. בדרך כלל זה פחות מהשריון.
  • אומדן המחיר לקריאה טיפוסית מגיע מ-POST /v1/credits/model-costs עם המפתח llm-structured:<model>. זה אומדן, ולכן הציגו אותו כ-≈N. ראו בדף ה-API קרדיטים.
  • כשלים: על כשל שהספק חייב עליו משלמים לפי השימוש הזה, והשגיאה מציינת כמה. דוגמאות: תשובה שלא עברה בדיקת תקינות גם אחרי הניסיונות החוזרים, סירוב או תשובה שנקטעה בתקרה. על כשל שהספק לא חייב עליו, הקרדיטים מוחזרים.

Claude Fable 5 זמין בנתיב הזה.

{
  "system": "You write production plans.",
  "input": "A rainy chase through Rome.",
  "jsonSchema": {
    "type": "object",
    "properties": { "title": { "type": "string" } },
    "required": ["title"]
  }
}

התגובה היא { jobId, output, usage: { inputTokens, outputTokens } }, ו-output בנוי לפי הסכמה שלכם.

  • שדות: system, input, jsonSchema, ובאופן אופציונלי schemaName (עד 64 תווים), llmModel, reasoningEffort, maxRetries, origin, advancedMode, temperature ו-maxTokens. השדות system ו-input מקבלים עד 100,000 תווים כל אחד, והשדה input צריך תו אחד לפחות.
  • מודל: בלי llmModel, הקריאה רצה ב-Gemini 3.6 Flash.
  • סכמה: השורש חייב להיות סכמה של אובייקט פשוט, עד 64 KB ועד 20 רמות עומק. מילות המפתח המותרות: properties, required, additionalProperties, items, הטיפוסים הבסיסיים, enum, const, הגבולות המספריים וגבולות האורך, multipleOf, exclusiveMinimum ו-description. מילות המפתח anyOf ו-oneOf מתקבלות רק מתחת לשורש. מילות המפתח not, if, then ו-else, מילות המפתח מסוג dependent, $ref חיצוני ו-combinators בשורש נדחים עם 400. מבנה anyOf של ענפי required מתחת לשורש מתקבל אבל לא נאכף, ולכן בדקו בעצמכם כללים שחוצים כמה שדות.
  • ניסיונות חוזרים: השדה maxRetries, מ-0 עד 3, עם ברירת מחדל של 2, הוא מספר הפעמים שתשובה לא תקינה חוזרת למודל עם שגיאת הבדיקה שלה.
  • פרמטרי דגימה: השדה maxTokens חל על כל קריאה, ואסור שיחרוג מהמגבלה של המודל עצמו. השדה temperature לא נלקח בחשבון, אלא אם שולחים גם advancedMode: true, שמריץ את הקריאה ב-API של יצרן המודל עצמו, בתעריף של אותו שירות.
  • משך: הקריאה סינכרונית ויכולה לרוץ כמה דקות. כל ניסיון יכול להימשך עד 240 שניות בכל אחד משני שירותים, ולכן המקרה הגרוע ביותר הוא 24 דקות עם ברירת המחדל של maxRetries, ו-32 דקות עם המקסימום. הגדילו את פסק הזמן של לקוח ה-HTTP שלכם, או השתמשו בצורת המשימה שלמטה. ברירת המחדל של ה-SDK ל-timeoutMs, 60 שניות, קצרה מדי.
  • שגיאות: 400 validation_error, 400 advanced_mode_unavailable, 401, 402, 500 internal_error, 502 llm_error אחרי שהניסיונות החוזרים נגמרו, 502 advanced_mode_unavailable ו-503 provider_unavailable. על הדחייה advanced_mode_unavailable, ראו את התיאור של advancedMode למעלה. שני קודים נוספים, 409 job_cancelled ו-503 job_start_failed, קשורים לשריון. ראו בדף ה-API שגיאות.

ב-SDK, קראו ל-client.llm.structured(body).

כמשימה

הנתיב POST /v1/llm/structured/jobs מקבל את אותו גוף בקשה ומחזיר מיד { jobId }. בדקו את הסטטוס עם GET /v1/jobs/:id/status מדי כמה שניות: ב-completed, השדה output_data הוא { output, inputTokens, outputTokens }, וב-failed, השדה error_message מציין למה. את הטיוטות שלכם תמצאו שוב עם GET /v1/jobs?type=llm-structured&origin=<your app>. הנתיב מקבל שלושה שדות נוספים:

  • label: שם תצוגה למשימה, עד 120 תווים.
  • videoUrl: טיוטה מסרטון. הסרטון מנותח קודם, כמשימה נפרדת שגם היא שלכם, במחיר של ניתוח וידאו, והניתוח מתווסף ל-input שלכם. בזמן שהניתוח רץ, השדה output_data.stage הוא analyzing, ואחר כך drafting.
  • videoAnalysis: האובייקט { llmModel?, selectionMode? } לניתוח הזה.

הקרדיטים לטיוטה משוריינים כשהמשימה נוצרת, תחת llm-structured:<model> (עם :direct ב-API של הספק עצמו). אחר כך המשימה מחויבת לפי מה שהטיוטה השתמשה בו. ביטול הטיוטה עם POST /v1/jobs/:id/cancel מבטל גם ניתוח שרץ. כשהניתוח נדחה, כל הקרדיטים ששוריינו לטיוטה מוחזרים. בהתקנה ששולחת את הקריאות שלה למודלי שפה ל-nodaro.ai, צורת המשימה מחזירה 503 provider_unavailable: בהתקנה כזו, השתמשו בקריאה הסינכרונית. ב-SDK, קראו ל-client.llm.structuredJob(body).

שאלות נפוצות

איך יוצרים תמונה עם ה-API של Nodaro?

שלחו POST /v1/generate-image עם השדות prompt ו-provider. התגובה כוללת jobId. בדקו את הסטטוס עם GET /v1/jobs/:id/status מדי כמה שניות עד שהוא completed, ואז קבלו את התוצאה מ-output_data.imageUrl. ב-SDK, המתודה client.nodes.runAndWait עושה את שני השלבים.

אילו רכיבים אפשר להריץ מה-API?

כל סוג רכיב שהנתיב GET /v1/nodes מחזיר. הנתיב הוא POST /v1/‎ ואחריו סוג הרכיב, וגוף הבקשה הוא ההגדרות של הרכיב ב-JSON. כמה רכיבי טקסט משתמשים בנתיב ארוך יותר, כגון ‎/v1/llm-chat/generate.

מהו האובייקט direction?

מפה שטוחה של מזהי בוררים, כגון ‎{ "shotSize": "wide-shot", "timeOfDay": "golden-hour" }‎, ששולחים עם יצירה של תמונה או וידאו. Nodaro כותב לפרומפט את הניסוח הבדוק שלו לכל מזהה. המזהים התקפים מגיעים מ-GET /v1/picker-catalogs.

איך שומרים על דמות עקבית דרך ה-API?

שלחו את התמונה של הדמות ב-connectedReferences, עם השדה source שערכו wired-character ועם שם הדמות ב-defaultName. הנתיב מצרף את התמונה וכותב לפרומפט את ההוראות לשמירה על הזהות, כמו שהעורך עושה.

האם נקודות הקצה של הגילוי צריכות אסימון?

לא. הנתיבים GET /v1/nodes, GET /v1/models, GET /v1/picker-catalogs ו-GET /v1/catalogs ציבוריים ונשמרים במטמון ל-5 דקות. הם חושפים רק נתוני קטלוג, ואף פעם לא מידע על החשבון שלכם.

מה קורה כשהפרומפט, יחד עם מזהי ההכוונה, ארוך מדי בשביל המודל?

Nodaro משמיט קודם את ביטויי ההכוונה, אחד אחד מהסוף, עד שהפרומפט נכנס במגבלה. ביטויי הנושא נשמטים אחרונים, והטקסט שכתבתם והייחוסים שלכם אף פעם לא נשמטים כדי לפנות להם מקום.

עודכן לאחרונה

בדף הזה