# משימות

> בדיקת הסטטוס והתוצאות של משימות ב-REST API של Nodaro, סינון הרשימה, דירוג ומועדפים, גודל התמונות, בדיקה של 100 משימות בקריאה אחת וביטול.

Source: https://nodaro.ai/he/docs/developers/api/jobs

**משימה** היא יחידת יצירה אחת ב-Nodaro: תמונה אחת, רינדור אחד של סרטון, קטע דיבור אחד. הרצה של רכיב מחזירה מזהה משימה, הרצה של תהליך יוצרת משימה אחת לכל רכיב AI, ונקודות הקצה של המשימות מדווחות על הסטטוס, ההתקדמות, התוצאה והקרדיטים של כל משימה. בודקים את הסטטוס של משימה מדי כמה שניות עד שהיא מגיעה ל-`completed`, ל-`failed` או ל-`cancelled`, ואז קוראים את התוצאה שלה מ-`output_data`.

## נקודות קצה
| שיטה | נתיב | מה היא עושה |
| --- | --- | --- |
| `GET` | `/v1/jobs/:id/status` | הסטטוס המצומצם לתשאול: סטטוס, התקדמות, תוצאה ושגיאה. |
| `GET` | `/v1/jobs/:id` | המשימה המלאה, כולל מה שנשלח (`input_data`) והקרדיטים שלה. |
| `GET` | `/v1/jobs` | המשימות שלכם, מהחדש לישן, בעמודים. |
| `GET` | `/v1/jobs/status?ids=…` | הסטטוס של עד 100 משימות, עם המזהים בשאילתה. |
| `POST` | `/v1/jobs/batch-status` | הסטטוס של עד 100 משימות, עם המזהים בגוף הבקשה. |
| `PUT` | `/v1/jobs/:id/rating` | דירוג של אחת מהמשימות שלכם כ-`good` או כ-`bad`, או מחיקת הדירוג. |
| `POST` | `/v1/jobs/from-upload` | רישום של תמונה שנערכה באפליקציה שלכם כמשימה. |
| `POST` | `/v1/gallery/favorite` | סימון משימה כמועדפת, או הסרת הסימון. |
| `GET` | `/v1/gallery/favorites` | המזהים של המשימות שסימנתם כמועדפות. |
| `POST` | `/v1/jobs/:id/cancel` | ביטול משימה ושחרור הקרדיטים ששוריינו לה. |
| `DELETE` | `/v1/jobs/:id` | העברת משימה לפח. הפרמטר `?forever=true` מוחק לצמיתות משימה שכבר נמצאת בפח. |
| `POST` | `/v1/jobs/:id/restore` | שחזור משימה שנמחקה מהפח. |
| `GET` | `/v1/trash` | הפח שלכם: פריטים שהוסרו מסשנים ומשימות שנמחקו. |
| `GET` | `/v1/component/execute/:jobId/wait-limit` | כמה זמן השרת ממתין להרצה של רכיב שמור. |
| `POST` | `/v1/generate-video-pro/:jobId/stop` | עצירת הרצה של רכיב יצירת וידאו Pro ושמירת המקטעים שהסתיימו. |
| `POST` | `/v1/generate-video-pro/continue` | המשך של הרצה של רכיב יצירת וידאו Pro, כמשימה חדשה. |
| `POST` | `/v1/credits/video-pro-estimate` | אומדן מחיר להרצה של רכיב יצירת וידאו Pro, בלי להתחיל אותה. |

אסימון OAuth צריך את ההרשאה `jobs:read` כדי לקרוא משימות. אסימוני API אישיים לא צריכים הרשאה. כדי ש-Nodaro יודיע לשרת שלכם כשמשימה מסתיימת, במקום תשאול, רשמו [נקודת קצה של Webhook](https://nodaro.ai/docs/developers/api/webhooks#job-events).

## קריאת משימה
**curl**

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

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

**TypeScript SDK**

```ts
const { data } = await client.jobs.getStatus(jobId)
if (data.status === 'completed') console.log(data.output_data)

// The full record, with input_data and credits:
const { data: job } = await client.jobs.get(jobId)
```

**CLI**

```bash
nodaro jobs get 0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10 --json
```

הנתיב `GET /v1/jobs/:id/status` נועד ללולאות תשאול: הוא משמיט את `input_data` ואת שדות העלות, ולכן הוא קל יותר מ-`GET /v1/jobs/:id`. שניהם מחזירים `{ "data": … }`, ושניהם מחזירים `404` למשימה שלא קיימת או שלא שייכת לכם. שדות המשימה כתובים ב-snake_case, כמו שהשרת שולח אותם.

| שדה | משמעות |
| --- | --- |
| `id` | מזהה המשימה. |
| `status` | איפה המשימה עומדת. ראו את הסעיף [סטטוסים של משימה](#job-statuses). |
| `progress` | מ-0 עד 100. |
| `output_data` | התוצאה. במשימות מדיה יש `imageUrl`, `videoUrl` או `audioUrl`, ולעיתים קרובות גם `thumbnailUrl`. במשימות אחרות יש שדות משלהן, כגון `text` או `json`. |
| `error_message` | הסבר מילולי למה המשימה נכשלה. |
| `error_hint` | סיבה מובנית לחמישה סוגים של כשל. ראו את הסעיף [למה משימה נכשלה](#why-a-job-failed). |
| `credit_status` | `reserved`, `committed`, `refunded` או `null`. ראו את הסעיף [הקרדיטים של משימה](#credits-of-a-job). |
| `recovering` | `true` בזמן שהפלטפורמה מתקנת משימה שה-worker שלה נעצר אחרי שהמודל כבר מסר את התוצאה. |
| `input_data` | רק במשימה המלאה. מה נשלח, אחרי תיקונים: למשל ה-`prompt` הסופי, ה-`userPrompt` שלכם ומזהי ה-`direction`. |
| `credits` | במשימה המלאה וברשימה. הקרדיטים ששוריינו למשימה כשהיא התקבלה. הסכום הזה אף פעם לא משתנה. |
| `credits_charged` | במשימה המלאה וברשימה. כמה המשימה עלתה אחרי החיוב הסופי של השריון שלה, כולל השלבים שהיא הריצה, או `null`. ראו את הסעיף [הקרדיטים של משימה](#credits-of-a-job). |
| `credits_held`, `credits_released` | במשימה המלאה וברשימה. השריון של ההרצה יחד עם השריונות של השלבים שלה, ומה שחזר ממנו אחרי החיוב הסופי של כל השריונות. ראו את הסעיף [הקרדיטים של משימה](#credits-of-a-job). |
| `job_type`, `source`, `source_detail` | רק במשימה המלאה. סוג המשימה, ומאיפה היא הגיעה: השדה `source` הוא `internal`, `mcp`, `app`, `cli`, `sdk`, `extension`, `web` או `api`, והשדה `source_detail` מציין את הלקוח, כגון `sdk/1.10.0`. |
| `session_id` | במשימה המלאה וברשימה. [סשן היצירה](https://nodaro.ai/docs/developers/api/nodes#sessions) שהמשימה נשמרה בו, או `null`. |
| `favorited`, `rating` | במשימה המלאה וברשימה. הסימון שלכם כמועדפת (`true` או `false`) והדירוג שלכם (`"good"`, `"bad"` או `null`). ראו את הסעיף [מועדפים ודירוגים](#favorites-and-ratings). |
| `created_at`, `started_at` | רק במשימה המלאה. חותמות זמן. |
| `completed_at` | מתי המשימה הסתיימה, לפי השעון של השרת, או `null` עד שהיא מסתיימת. גם נתיב הסטטוס מחזיר אותו. |

השדות `input_data` ו-`output_data` הם תצוגות ציבוריות: שדות שקיימים רק בשביל השרת מוסרים מהם לכל מי שקורא אותם.

ב-`output_data` של משימה של רכיב [החלת רשימת עריכה](https://nodaro.ai/docs/nodes/video/apply-edl) מצוין ממה הרינדור נחתך. השדה `quality` הוא `"proxy"` בתצוגה מקדימה ו-`"final"` ברינדור סופי, והשדה `clipKey` מציין את הקליפ מהתוכנית כשהבקשה שלחה קליפ כזה. בקריאה של משימה ישנה יותר של רכיב החלת רשימת עריכה מופיעה האיכות שבה היא הוזמנה.

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

| שדה | סוג | משמעות |
| --- | --- | --- |
| `width`, `height` | integer | הגודל של `imageUrl` בפיקסלים, כפי שהקובץ שמור: מה שאתם מורידים, כולל סימן המים של המסלול החינמי. הכיוון לפי EXIF כבר הוחל, ולכן זה הגודל שדפדפן מציג. |
| `images` | `{ url, width, height }[]` | לצד `imageUrls`, במשימה שיצרה כמה תמונות: פריט אחד לכל תמונה, בסדר של `imageUrls`. בפריט שאי אפשר היה לקרוא את הגודל שלו יש רק `url`. השדה `imageUrls` עצמו נשאר מערך של מחרוזות. |

```json
{
"imageUrl": "https://cdn.nodaro.ai/images/<jobId>.png",
"imageUrls": ["https://cdn.nodaro.ai/images/<jobId>.png", "https://cdn.nodaro.ai/images/<jobId>-v1.png"],
"width": 1024,
"height": 1536,
"images": [
{ "url": "https://cdn.nodaro.ai/images/<jobId>.png", "width": 1024, "height": 1536 },
{ "url": "https://cdn.nodaro.ai/images/<jobId>-v1.png", "width": 1024, "height": 1536 }
]
}
```

התייחסו לשלושת השדות כאופציונליים. במשימות שהסתיימו לפני שהגודל התחיל להירשם אין אף אחד מהם, וגודל שהשרת לא הצליח לקרוא לא מופיע, ואף פעם לא מנוחש. השדות מופיעים בכל קריאה של משימה: `GET /v1/jobs`, `GET /v1/jobs/:id` ו-`GET /v1/jobs/:id/status`. כלי המשימות של ה-MCP, `get_job`, `wait_for_job` ו-`get_asset`, מחזירים `width` ו-`height` לצד `outputUrl`.

## סטטוסים של משימה
| סטטוס | סופי | משמעות |
| --- | --- | --- |
| `pending`, `queued`, `processing` | לא | המשימה ממתינה להתחיל, או שהיא כבר רצה. |
| `pending_review` | לא | התוצאה קיימת, והפריסה מעכבת אותה לבדיקה של אדם. המשיכו לבדוק את הסטטוס. |
| `completed` | כן | התוצאה נמצאת ב-`output_data`. |
| `failed` | כן | `error_message` ו-`error_hint` מסבירים למה. |
| `cancelled` | כן | ביטלתם את המשימה, או שהפלטפורמה ביטלה אותה. |

**משימות בהתאוששות.** כש-worker נעצר אחרי שהמודל כבר מסר את התוצאה, המשימה נשארת בסטטוס `processing` עם `recovering: true` בזמן שהפלטפורמה מתקנת אותה. אחר כך המשימה מסתיימת מעצמה, או שהקרדיטים עליה מוחזרים אוטומטית. במודלים איטיים זה יכול לקחת עשרות דקות, יותר מזמן ההמתנה שה-SDK מגדיר כברירת מחדל: השגיאה `JobTimeoutError` מ-`runAndWait` לא מבטלת את המשימה, ולכן בדקו אותה שוב מאוחר יותר.

**משימות שממתינות לבדיקה.** בפריסה שרושמת מדיניות בדיקה, משימה יכולה לעבור לסטטוס `pending_review`. העבודה הסתיימה, הקרדיטים נשארים בסטטוס `reserved` לאורך כל ההמתנה, ואדם מחליט אם לשחרר את התוצאה. אחר כך המשימה מסתיימת בסטטוס `completed` (אושרה), `failed` עם הרמז `policy-block` (נדחתה) או `cancelled`. אפשר לבטל משימה שממתינה לבדיקה כמו כל משימה שבעיצומה. אל תריצו את הבקשה שוב, כי גם משימה כפולה תמתין לבדיקה. כשהפריסה קובעת מועד אחרון לבדיקה, משימה שאף אחד לא בדק בזמן נדחית: היא מסתיימת בסטטוס `failed`, הקרדיטים המשוריינים מוחזרים, והתוצאה שעוכבה נמחקת. משימה שממתינה לבדיקה אף פעם לא מאושרת אוטומטית. המתודה `runAndWait` של ה-SDK זורקת `JobHeldError` בבדיקה הראשונה שרואה `pending_review`, וה-CLI עם `--watch` יוצא עם קוד היציאה `3`.

## תשאול נכון
- **בדקו את הסטטוס כל 2–5 שניות.** משימה משנה מצב בתוך שניות, לא בתוך אלפיות שנייה.
- **קריאות סטטוס לא נספרות במגבלת הקצב של האסימון.** רק הרצות של תהליכים ורשימות של תהליכים נספרות במגבלה לדקה של אסימון API אישי. ראו את דף ה-API [מגבלות קצב](https://nodaro.ai/docs/developers/api/rate-limits).
- **בדקו את המצב של משימות רבות בקריאה אחת.** השתמשו ב[נקודות הקצה לאצווה](#poll-many-jobs-at-once) במקום לשלוח בקשה נפרדת לכל משימה.
- **תנו ללקוח לחכות בשבילכם.** המתודה `client.nodes.runAndWait` של ה-SDK בודקת את הסטטוס כל 2 שניות, עד 15 דקות, וה-CLI עם `--watch` בודק את הסטטוס עד שהמשימה מסתיימת.

## למה משימה נכשלה
טבלת השגיאות בדף ה-API [שגיאות](https://nodaro.ai/docs/developers/api/errors) מכסה בקשות שלא יצרו משימה בכלל. במשימה שנכשלת מאוחר יותר יש `error_message`, ובחמישה סוגים של כשל גם `error_hint` מובנה.

**מסנן הבטיחות של מודל חסם את הבקשה:**

```json
{ "kind": "safety-block", "class": "safety", "retried": true, "suggestedProvider": "nano-banana-pro" }
```

- השדה `class` הוא `copyright`, `likeness` או `safety`. חסימה מסוג `copyright` או `likeness` היא סופית: אותה בקשה אף פעם לא תעבור.
- במודלים מסוימים, מסנן `safety` לא תמיד עקבי. ב-[GPT Image 2](https://nodaro.ai/docs/models/image/gpt-image-2), ב-[GPT Image 2.5 Flare](https://nodaro.ai/docs/models/image/gpt-image-2-5-flare) וב-[GPT Image 2.5 Sunburst](https://nodaro.ai/docs/models/image/gpt-image-2-5-sunburst), Nodaro מנסה שוב את אותה בקשה פעם אחת, בלי עלות נוספת. השדה `retried` מציין אם הניסיון החוזר הזה כבר רץ.
- השדה `suggestedProvider` מופיע רק כשיש למודל חלופה מומלצת. זה מזהה של מודל אמיתי: שלחו אליו את אותו פרומפט ואת אותם ייחוסים.
- הערך `subject: "input_video"` מופיע כשהספק דחה את סרטון הקלט של המשימה עצמו, ולא את הפרומפט, את אחת מתמונות הייחוס או את התוצאה. שלחו קליפ אחר.
- הערך `subject: "input_image"`, תמיד עם `class: "copyright"`, מופיע כשהספק דחה אחת מתמונות הקלט של המשימה, כי ייתכן שהיא מוגנת בזכויות יוצרים. שלחו תמונה אחרת: ניסוח מחדש של הפרומפט לא יעזור.
- הערך `subject: "prompt"` מופיע, בכל `class`, כשהמילים של הספק עצמו ציינו את הפרומפט. הפתרון הוא לשנות את הפרומפט.
- הערך `subject: "audio"` מופיע, בכל `class`, כשהמילים של הספק עצמו האשימו את האודיו שנוצר, ולא את התמונה.
- התייחסו ל-`subject` שאתם לא מכירים כאילו הוא לא קיים.

**המדיניות של פריסה דחתה את המשימה:**

```json
{ "kind": "policy-block", "policyId": "brand-safety", "reason": "This image was not approved for release.", "hookPoint": "result" }
```

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

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

```json
{ "kind": "credits", "code": "insufficient_credits" }
```

- השדה `code` הוא הקוד של הדחייה עצמה, בכתיב snake case באותיות קטנות: הערך `insufficient_credits` כשהיתרה לא הספיקה לשלב, או מגבלה של תוכנית או של סביבת עבודה, כגון `free_video_limit`, `instance_cap_reached`, `budget_exceeded`, `member_cap_exceeded` או `user_allowance_exceeded`. התייחסו לקוד לא מוכר כמו ל-`insufficient_credits`.
- הקרדיטים של המשימה מוחזרים. בקשו מהאדם לטעון קרדיטים, או להגדיל את המגבלה, ואז הריצו את הבקשה שוב. עד אז, אותה בקשה תיכשל באותה דרך.

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

```json
{ "kind": "input-refused", "subject": "input_video" }
```

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

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

```json
{ "kind": "request-refused", "subject": "input_video" }
```

הערך `subject: "input_video"` מופיע רק כשהמילים של הספק מציינות שהבעיה בסרטון הקלט, למשל האורך או הגודל שלו, או שלא נמצאה בו דמות. במקרה כזה, קליפ אחר הוא מה שיכול לשנות את התוצאה. אותה בקשה נדחית באותה דרך, ולכן אל תריצו אותה שוב בלי שינוי. שנו את תמונות הקלט, את הסרטון, את הפרומפט או את ההגדרות. זו לא חסימה של מדיניות תוכן. במשימה שמורכבת משלבים, כגון הרצה של Nodaro Motion או של טרנד, זו דחייה של שלב אחד.

**בכל כשל אחר אין `error_hint`.** כשמודל דוחה את הבקשה עצמה, כי ההגדרות או המדיה בקלט לא תקינות למודל הזה, השדה `error_message` אומר את זה: שנו את ההגדרות או את המדיה לפני שתריצו שוב. לפעמים המודל דוחה את הבקשה בלי סיבה, רק עם ההודעה הכללית שלו "Generation failed. Please try again later." (היצירה נכשלה. נסו שוב מאוחר יותר). במקרה כזה, השדה `error_message` אומר שהמודל לא נתן סיבה, ושהגורם יכול להיות זמני או במדיה שבקלט, כגון הגודל או הפורמט שלה. הריצו את המשימה הזו שוב פעם אחת, ואם היא נכשלת שוב, החליפו את המדיה בקלט. שגיאה בצד של המודל תמיד שווה ניסיון חוזר, יהיה הניסוח שלה אשר יהיה. השדה `error_hint` מופיע בכל מטען של משימה שיש בו `error_message`: המשימה המלאה, נתיבי הסטטוס, הרשימה ושני נתיבי האצווה.

## הקרדיטים של משימה
השדה `credit_status` משקף את שריון הקרדיטים של המשימה:

| ערך | משמעות |
| --- | --- |
| `reserved` | הקרדיטים משוריינים בזמן שהמשימה רצה. |
| `committed` | המשימה מסרה תוצאה, והקרדיטים נגבו. |
| `refunded` | השריון שוחרר, למשל אחרי חסימה של מסנן בטיחות. |
| `null` | אין למשימה רשומת קרדיטים לדווח עליה. |

השדה מופיע ב-`GET /v1/jobs`, ב-`GET /v1/jobs/:id`, ב-`GET /v1/jobs/:id/status` וב-`GET /v1/jobs/status`, ואף פעם לא ב-`POST /v1/jobs/batch-status`. על יצירה שמסתיימת בחסימה של מסנן בטיחות או של מדיניות תמיד מקבלים החזר. החריג הנדיר הוא משימה שהחיוב הסופי של הקרדיטים שלה כבר נסגר לפני שמדיניות דחתה את התוצאה שלה. ראו את דף ה-API [קרדיטים](https://nodaro.ai/docs/developers/api/credits).

השדה `credits` של משימה הוא הסכום ש**שוריין** למשימה עצמה כשהיא התקבלה, והוא אף פעם לא משתנה. הנתיבים `GET /v1/jobs` ו-`GET /v1/jobs/:id` מחזירים גם את `credits_charged`: כמה המשימה עלתה אחרי החיוב הסופי של השריון שלה, לפי אותה רשומת קרדיטים.

- השדה `credits_charged` יכול להיות נמוך מ-`credits`. יש משימות שמשוריין להן יותר ממה שבסוף נדרש, למשל כדי לכסות רינדור חוזר אפשרי או אורך שנמדד אחרי ההרצה. השאר חוזר ליתרה שלכם.
- כשהקרדיטים ששוריינו למשימה עצמה הוחזרו, השדה `credits_charged` הוא `0` ועוד הקרדיטים שנגבו על שלבים שהחיוב שלהם כבר נסגר. למשל, בהרצה של Nodaro Motion שהקרדיטים שלה הוחזרו, אבל על שלבי הייחוס והמסכה שלה נגבו קרדיטים, הערכים הם `credit_status: "refunded"` ו-`credits_charged: 165`.
- השדה `credits_charged` הוא `null` כל עוד השריון של המשימה עצמה פתוח (`credit_status: "reserved"`), גם כשהחיוב של חלק מהשלבים שלה כבר נסגר. הוא `null` גם כששום דבר בהרצה לא שוריין.

כדי לחשב כמה משימות עלו, סכמו את `credits_charged`, לא את `credits`. למשל, משימה ששוריינו לה 888 קרדיטים, ובחיוב הסופי נגבו עליה 444, מחזירה `credits: 888`, `credits_charged: 444` ו-`credit_status: "committed"`.

### משימות שמריצות משימות אחרות
השדה `credits_charged` הוא החיוב של המשימה **כהרצה, כולל השלבים שלה**. יש משימות שמריצות בשבילכם משימות אחרות. למשל, הרצה של [Nodaro Motion](https://nodaro.ai/docs/developers/api/cast-swap) מכינה את הייחוסים שלה, יוצרת מסכה ומרנדרת את הסרטון, וכל אחד מאלה הוא שלב נפרד. שלב אף פעם לא מופיע ברשימה בפני עצמו, והקרדיטים עליו נגבים כשהחיוב שלו נסגר.

- שלב שהשריון שלו עדיין פתוח לא מוסיף כלום בינתיים, ושלב שהקרדיטים עליו הוחזרו מוסיף `0`.
- השדה `credits_held` הוא השריון של ההרצה: ה-`credits` של המשימה עצמה ועוד השריונות של השלבים שלה. במשימה בלי שלבים, הוא זהה ל-`credits`.
- השדה `credits_released` הוא מה שחזר מהשריון (`credits_held` פחות `credits_charged`), אחרי החיוב הסופי של כל השריונות בהרצה. עד אז הוא `null`.
- השדות `credits` ו-`credit_status` נשארים של המשימה עצמה.
- כשלרגע אי אפשר לקרוא את השלבים, הערך של `credits_charged`, `credits_held` ו-`credits_released` הוא `null`. המשמעות היא ״לא ידוע״, ואף פעם לא סכום נמוך יותר.

למשל, תצוגה מקדימה של Nodaro Motion שהשריון של המשימה עצמה היה 44, עם שני שלבי ייחוס של 66 כל אחד, מסכה של 33 וסרטון ששוריינו לו 3,564 קרדיטים ובחיוב הסופי נגבו עליו 854, מחזירה `credits: 44`, `credits_charged: 1063`, `credits_held: 3773` ו-`credits_released: 2710`.

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

## רשימת המשימות שלכם
הנתיב `GET /v1/jobs` מחזיר את המשימות שלכם, מהחדש לישן, בצורה `{ data: Job[], next }`. משימת משנה, כלומר משימה שמשימה אחרת התחילה כשלב בעבודה שלה, לא מופיעה ברשימה. מפתחות פלט שהשם שלהם מתחיל ב-`__` מיועדים לשרת בלבד, ואף קריאה של משימה לא מחזירה אותם.

| פרמטר שאילתה | משמעות |
| --- | --- |
| `limit` | גודל העמוד, עד 100. |
| `cursor` | הערך `next` מהעמוד הקודם. |
| `status` | סטטוס משימה אחד או יותר: `pending`, `queued`, `processing`, `pending_review`, `completed`, `failed` או `cancelled`. סטטוס לא מוכר נדחה עם `400 validation_error`. |
| `type` | נתיב אחד או יותר שיצרו את המשימה, כגון `llm-structured` או `video-analysis`, עד 20. |
| `origin` | אפליקציית הלקוח ששלחה את המשימה, בהתאמה מדויקת, כגון `studio`. |
| `source` | ממשק אחד או יותר שממנו נוצרה המשימה: `mcp`, `cli`, `sdk`, `web`, `extension`, `app`, `api` או `internal`, כלומר השדה `source` של המשימה. הערך `source=mcp` מחזיר את מה שלקוחות ה-MCP שלכם, כגון Claude או ChatGPT, יצרו. |
| `favorited` | `true` מחזיר את המשימות שסימנתם כמועדפות, ו-`false` את אלה שלא סימנתם. |
| `rating` | `good`, `bad`, `rated` (דירוג כלשהו) או `unrated`. |
| `projectId` | המשימות שנמצאות עכשיו בסשן של הפרויקט הזה, כל אחת פעם אחת. הערך `none` מחזיר את המשימות שנמצאות בסשן שלא שייך לאף פרויקט. אי אפשר לשלב אותו עם `inSession=false`. |
| `inSession` | `false` מחזיר את המשימות שלא נמצאות עכשיו באף סשן, שהאפליקציה מציגה תחת **כללי**. הערך `true` מחזיר את המשימות שנמצאות בסשן אחד לפחות. |
| `withSessions` | `true` מוסיף לכל משימה את `sessions: [{ id, title, projectId }]`: הסשנים שהיא נמצאת בהם. |
| `batchId` | המשימות של אצווה אחת של רכיב יצירת תמונה. ראו בדף ה-API [כמה תמונות בקריאה אחת](https://nodaro.ai/docs/developers/api/nodes#several-images). |
| `attachToCharacterId` | המשימות של דמות אחת. ראו את דף ה-API [דמויות](https://nodaro.ai/docs/developers/api/characters). |

הפרמטרים `status`, `type` ו-`source` מקבלים רשימה מופרדת בפסיקים (`status=failed,cancelled`) או פרמטר שחוזר על עצמו (`type=a&type=b`). כל מסנן דורש התאמה מדויקת, והמסננים משתלבים זה עם זה. בעמוד יכולות להיות פחות רשומות מ-`limit`, ואפילו אף רשומה, ועדיין יהיה בו `next`: המשיכו לעבור לעמוד הבא כל עוד יש `next`, ואף פעם אל תסתמכו על ספירת הרשומות.

```ts
const { data: runs, next } = await client.jobs.list({ type: 'llm-structured', origin: 'my-app' })
```

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

- **מועדף** הוא סימנייה על משימה: אחת מהמשימות שלכם, בכל סטטוס, או משימה ציבורית של כל משתמש שהסתיימה ומופיעה בגלריה.
- **דירוג** הוא חוות הדעת שלכם על אחת מהמשימות שלכם, `good` או `bad`.

| שיטה | נתיב | גוף הבקשה או פרמטרי השאילתה | מה היא עושה |
| --- | --- | --- | --- |
| `PUT` | `/v1/jobs/:id/rating` | `{ "rating": "good" \| "bad" \| null }` | דירוג של אחת מהמשימות שלכם, או מחיקת הדירוג שלה עם `null`. השדה `rating` נדרש, ולכן מחיקה תמיד מפורשת. מחזירה `{ data: { jobId, rating } }`. |
| `POST` | `/v1/gallery/favorite` | `{ "jobId": "..." }` | סימון משימה כמועדפת, או הסרת הסימון כשהיא כבר מועדפת. מחזירה `{ favorited }`, המצב אחרי ההחלפה. |
| `GET` | `/v1/gallery/favorites` | אין | המזהים של המשימות שסימנתם כמועדפות, מהחדש לישן: `{ data: string[] }`. |
| `GET` | `/v1/gallery` | `type`, `userId`, `favoritesOnly=true`, `limit` (1–50, ברירת המחדל 20), `cursor` | הגלריה הציבורית, החל מהמשימות שהסתיימו לאחרונה. עם ה-`userId` שלכם והאסימון שלכם, הפרמטר `favoritesOnly=true` מצמצם את הרשימה למועדפים שלכם. |

- **בכל משימה יש `favorited` ו-`rating`** ב-`GET /v1/jobs` וב-`GET /v1/jobs/:id`. כשלרגע השרת לא מצליח לקרוא אותם, המשימות עדיין מוחזרות, ושני השדות לא מופיעים. התייחסו לשדה חסר כ״לא ידוע״, אף פעם לא כ-`false`: החלפת מצב של מועדף שלא ידוע אם הוא מסומן עלולה להסיר את הסימון.
- **דירוג אחד לכל משימה**, של הבעלים שלה. על משימה של כל אדם אחר התגובה היא `404 not_found`. דירוג שהוא לא `good`, `bad` או `null` נדחה עם `400 validation_error`.
- **משימה פרטית של אדם אחר**: ניסיון לסמן אותה כמועדפת נדחה עם `404 not_found`, ושום דבר לא נשמר. הסרה של סימון מועדף תמיד עובדת.
- **הרשאות:** אסימון של אפליקציית OAuth צריך את `assets:write` לשתי פעולות הכתיבה, ואת `assets:read` או `jobs:read` כדי לקבל את רשימת המועדפים שלכם. קריאות המשימות נשארות תחת `jobs:read`.
- **פריסה שמסתירה את הגלריה** מחזירה `404` בכל נתיב של `/v1/gallery`.

```bash
# Rate a job good, favorite it, then list your good favorites that completed
curl -s -X PUT "https://app.nodaro.ai/v1/jobs/$JOB/rating" \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"rating": "good"}'
curl -s -X POST "https://app.nodaro.ai/v1/gallery/favorite" \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"jobId\": \"$JOB\"}"
curl -s "https://app.nodaro.ai/v1/jobs?rating=good&favorited=true&status=completed" \
  -H "Authorization: Bearer $NODARO_API_KEY" | jq '.data[] | {id, favorited, rating}'
```

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

1. אחסנו את התמונה הערוכה עם `POST /v1/upload`, ושמרו את ה-`assetId` שלה. ראו את דף ה-API [העלאות](https://nodaro.ai/docs/developers/api/uploads).
2. אם תרצו, אחסנו גם את מצב העיצוב של העורך עם `POST /v1/upload-json`, כדי שאפשר יהיה לפתוח את העריכה שוב. נקודת הקצה מקבלת כל גוף JSON עד 25 MB ומחזירה `{ url }`.
3. קראו ל-`POST /v1/jobs/from-upload` עם `{ assetId, sourceJobId?, sourceImageUrl?, sourceAssetId?, editStateUrl?, sessionId? }`.

הנתיב רושם את ההעלאה כמשימת `image-edit` שהסתיימה מיד, ומחזיר `{ data: Job }`. הוא מחזיר `201` כשהוא רושם את התמונה, ו-`200` כשה-`assetId` הזה כבר נרשם בעבר, עם אותה משימה.

- **חינמי ופרטי.** רישום המשימה לא עולה כלום, כי האחסון של הקובץ נספר כשהעליתם אותו. המשימה אף פעם לא ציבורית: היא מופיעה בהיסטוריית המשימות, בגלריה ובספרייה שלכם, אף פעם לא בגלריה הציבורית.
- **מה יש במשימה.** השדה `output_data.imageUrl` הוא ההעלאה, עם `thumbnailUrl`, `width` ו-`height`. השדה `input_data` כולל את `type: "image-edit"`, את ה-`assetId` ואת המקור, כלומר `sourceJobId` או `sourceAssetId`, ועוד `sourceImageUrl`, התמונה של המקור. במשימה שיצרה כמה תמונות, שלחו כ-`sourceImageUrl` את התמונה שערכתם. עריכה של תמונה של דמות, אובייקט, יצור או מיקום שומרת את הקישור הזה, ולכן היא מופיעה עם הנכס הזה. הנתיב `GET /v1/jobs?type=image-edit` מחזיר את המשימות האלה.
- **העלאה אחת, משימה אחת.** בקשה עם אותו `assetId` מחזירה שוב את אותה משימה, ולכן ניסיון חוזר או לחיצה כפולה אף פעם לא יוצרים שתי משימות. ניסיון חוזר גם משלים משימה שניסיון קודם לא סיים, ולכן בתגובת `2xx` יש תמיד משימה שהסתיימה. המשימה שומרת את המקור, את מצב העיצוב ואת הסשן של הבקשה שיצרה אותה. הערכים של ניסיון חוזר לא מוחלים. כדי להציג את המשימה בסשן נוסף, הוסיפו אותה שם עם `POST /v1/sessions/:id/items`.
- **דחיות.** הבקשה נדחית עם `404 not_found` כשהנכס, המקור או הסשן לא שייכים לכם. היא נדחית עם `400 validation_error` כשהנכס הוא לא תמונה, או הוא לא קובץ שאחסנתם. אותה שגיאה חוזרת כשלמשימת המקור אין תמונה מוגמרת, כש-`sourceImageUrl` הוא לא אחת מהתמונות שלה, כששני המקורות נשלחים, או כש-`editStateUrl` הוא לא כתובת ש-`POST /v1/upload-json` החזיר. היא נדחית עם `409 conflict` כשכבר השתמשתם ב-`image-edit:<assetId>` כ-`Idempotency-Key` של בקשה אחרת, ועם `422 job_blocked` כשמדיניות המשימות של הפריסה דוחה את התמונה, בכל ניסיון חוזר.
- **מחיקה.** מחיקת המשימה משאירה את הקובץ שהועלה בהעלאות שלכם. מחיקת ההעלאה מהספרייה שלכם משאירה את הקובץ כל עוד המשימה הזו עדיין מציגה אותו.

אסימון של אפליקציית OAuth צריך את ההרשאה `assets:write`.

```bash
# Record an edited image next to the job it was made from, in a session
curl -s -X POST "https://app.nodaro.ai/v1/jobs/from-upload" \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"assetId\": \"$ASSET\", \"sourceJobId\": \"$JOB\", \"sessionId\": \"$SESSION\"}" | jq '.data | {id, status, output_data}'
```

## תשאול של כמה משימות בבת אחת
שתי נקודות קצה מחזירות את הסטטוס של עד 100 משימות בסבב בקשה אחד:

**GET /v1/jobs/status**

```bash
curl -s "https://app.nodaro.ai/v1/jobs/status?ids=$JOB_A,$JOB_B,$JOB_C" \
  -H "Authorization: Bearer $NODARO_API_KEY"
```

```json
{
"jobs": [
{ "id": "0f1a9c2e-…", "status": "completed", "output_data": { "imageUrl": "https://…/a.png" }, "error_message": null, "error_hint": null, "credit_status": "committed" },
{ "id": "7d3e5f60-…", "status": "processing", "output_data": null, "error_message": null, "error_hint": null, "credit_status": "reserved" }
]
}
```

**POST /v1/jobs/batch-status**

```bash
curl -s -X POST https://app.nodaro.ai/v1/jobs/batch-status \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"jobIds\": [\"$JOB_A\", \"$JOB_B\", \"$JOB_C\"]}"
```

התגובה היא `{ "data": [ … ] }`, עם `id`, `status`, `output_data`, `error_message` ו-`error_hint` לכל משימה, ובלי `credit_status`.

מזהים שלא קיימים, או ששייכים למישהו אחר, מושמטים בלי שגיאה. השוו את התגובה לרשימת המזהים שלכם.

## ביטול או מחיקה של משימה
הנתיב `POST /v1/jobs/:id/cancel` מבטל משימה ומשחרר את הקרדיטים ששוריינו לה. התגובה היא `{ "success": true, "cancelled": 1 }`. אפשר לבטל גם משימה שממתינה לבדיקה בסטטוס `pending_review`. ביטול של משימה מבטל גם את משימות המשנה שלה שעדיין רצות. משימת משנה שהסתיימה נשארת כמו שהיא, ומשימת משנה שכבר נשלחה למודל מסתיימת, כמו כל משימה שבעיצומה.

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

- על משימה שהקריאה שלה כבר התחילה, הנתיב `POST /v1/jobs/:id/cancel` מחזיר `{ "success": true, "cancelled": 0, "inFlight": true }`. המשימה מסתיימת, והקרדיטים נגבים עליה רק לפי השימוש בפועל.
- הכפתור **עצירה** בקנבס, `POST /v1/jobs/cancel-all` וביטול של הרצת תהליך (`POST /v1/workflow-executions/:id/cancel`) מבטלים את המשימה. נגבים עליה הקרדיטים שהספק כבר חייב עליהם, ושאר הקרדיטים ששוריינו לה מוחזרים.
- על משימה שנעצרה לפני שהקריאה שלה התחילה מקבלים החזר, בכל דרך שבה היא בוטלה. החריג הוא מה שניסיון קודם של אותה משימה כבר השתמש בו, למשל ניסיון חוזר אחרי ניסיון שחויב. על השימוש הזה משלמים.

הנתיב `DELETE /v1/jobs/:id` מעביר משימה ל[פח](#the-trash) ומחזיר `{ "success": true }`. רק הבעלים של המשימה יכול למחוק אותה. משימה שעדיין רצה ממשיכה לרוץ, ולכן בטלו אותה קודם אם העבודה שלה צריכה להיפסק. כשמוחקים משימה, הקרדיטים לא מוחזרים. אפליקציות OAuth צריכות את ההרשאה `assets:write` כדי למחוק או לשחזר משימה.

**curl**

```bash
curl -s -X POST https://app.nodaro.ai/v1/jobs/$JOB_ID/cancel \
  -H "Authorization: Bearer $NODARO_API_KEY"
```

**TypeScript SDK**

```ts
const { cancelled } = await client.jobs.cancel(jobId)
await client.jobs.delete(jobId)
```

**CLI**

```bash
nodaro jobs cancel 0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10
```

כדי לעצור הרצה שלמה של תהליך, בטלו במקום זאת את ההרצה עצמה: ראו את דף ה-API [הרצות](https://nodaro.ai/docs/developers/api/executions).

## הפח
גם הסרה של פריט מסשן וגם מחיקה של משימה מעבירות אותם ל**פח**.

- **פריט שהוסר** נשאר עד שתשחזרו אותו עם `POST /v1/sessions/:id/items/:jobId/restore`, או עד שתמחקו אותו לצמיתות עם `DELETE /v1/sessions/:id/items/:jobId?forever=true`. הסרה אף פעם לא מוחקת את המשימה. פריט שלא נמצא באף סשן פעיל מוצג תחת **כללי**.
- **משימה שנמחקה** נעלמת מכל קריאה: רשימות המשימות והקריאות לפי מזהה, בדיקות הסטטוס, הגלריה, הפידים והתצוגות המקדימות של הסשנים, כלי ה-MCP וה-CLI. אפשר לשחזר אותה במשך 30 ימים. הנתיב `POST /v1/jobs/:id/restore` מחזיר אותה לכל סשן שהיא הייתה בו.
- **אחרי 30 ימים** משימה שנמחקה נמחקת לצמיתות, יחד עם המדיה הפרטית שלה. עותק שנשמר בספרייה נשאר.
- **מחיקה לצמיתות עכשיו.** הנתיב `DELETE /v1/jobs/:id?forever=true` מוחק לצמיתות משימה שכבר נמצאת בפח. על משימה שלא נמצאת בפח הוא מחזיר `409 not_in_trash`.
- **הקרדיטים לא מוחזרים** כשמשימה נמחקת, וגם לא כשהיא נמחקת לצמיתות.

הנתיב `GET /v1/trash` מחזיר את מה שיש בפח, מהחדש לישן, עמוד אחד בכל פעם (`limit` מ-1 עד 100, ברירת המחדל 50, ו-`cursor`). כל רשומה היא `{ kind: "removed", removedAt, session: { id, title, projectId }, job }` או `{ kind: "deleted", deletedAt, purgeAt, job }`. פריט שהסרתם, שגם את המשימה שלו מחקתם, מופיע פעם אחת, כמשימה שנמחקה.

| פרמטר שאילתה | משמעות |
| --- | --- |
| `projectId` | מזהה פרויקט: הפריטים שהוסרו מהסשנים של הפרויקט, והמשימות שנמחקו שהיו בסשן שלו. `none`: הסשנים שלא שייכים לאף פרויקט, ו**כללי**. |
| `tool` | מה שנמצא או היה בסשן של כלי היצירה הזה. למשימה שאף פעם לא הייתה בסשן אין כלי, ולכן הפרמטר `tool` משמיט אותה. |
| `type` | ה-`input_data.type` של המשימה, מופרד בפסיקים. סננו לפי `type` בלבד, עם סוגי המשימות של הכלי שלכם, כדי לכלול משימות שנמחקו ואף פעם לא היו בסשן. |

מחיקה של סשן מוחקת גם את הפריטים שהוסרו ממנו.

## הרצות של רכיבים שמורים
הנתיב `POST /v1/component/execute` מריץ [רכיב שמור](https://nodaro.ai/docs/nodes/automate/component) ברקע ומחזיר `202` עם `{ jobId }`. בדקו את הסטטוס של המשימה הזו מדי כמה שניות, כמו בכל משימה אחרת. עם אסימון של אפליקציית OAuth, הנתיב דורש את ההרשאה `workflows:execute`, וקריאת מגבלת ההמתנה שמתוארת בהמשך דורשת `jobs:read`. השרת נותן להרצה של רכיב שמור 90 דקות, ועוד תקציב הזמן של כל רינדור ארוך שבתוכה, כגון הרינדור הסופי של רכיב [החלת רשימת עריכה](https://nodaro.ai/docs/nodes/video/apply-edl).

לקוח עם מגבלת זמן משלו יכול לשאול כמה זמן השרת ימתין:

```bash
curl -s https://app.nodaro.ai/v1/component/execute/$JOB_ID/wait-limit \
  -H "Authorization: Bearer $NODARO_API_KEY"
```

```json
{ "data": { "budgetExcessMs": 0, "waitLimitMs": 5400000, "pendingBudgetedNodes": true } }
```

- השדה `waitLimitMs` הוא זמן ההמתנה של השרת להרצה הזו: 90 דקות ועוד `budgetExcessMs`.
- השדה `budgetExcessMs` נשאר `0` עד שההרצה מתחילה רינדור ארוך.
- השדה `pendingBudgetedNodes` הוא `true` כל עוד רינדור ארוך עדיין לא התחיל, וכל עוד ההרצה עצמה לא התחילה. לכן הערך `0` ב-`budgetExcessMs` עדיין לא אומר שאין בפנים שום דבר ארוך.

שני הערכים יכולים להשתנות בזמן שההרצה נמשכת, ולכן שאלו שוב כשמגיעים ל-`waitLimitMs`. הנתיב עונה רק לבעלים של ההרצה, ומחזיר `404` לכל אחד אחר ולמשימות שהן לא הרצות של רכיב שמור. העורך עצמו פועל לפי הכלל הזה: הוא ממתין 30 דקות להרצה שאין בה שום דבר ארוך, `waitLimitMs` אחרי שרינדור ארוך התחיל, ולפחות 90 דקות כל עוד `pendingBudgetedNodes` הוא `true`, ואז שואל שוב.

## הרצות של רכיב יצירת וידאו Pro
רכיב [יצירת וידאו Pro](https://nodaro.ai/docs/nodes/video/generate-video-pro) יוצר סרטונים ארוכים מקטע אחר מקטע, ושומר את ההתקדמות שלו בין המקטעים, ולכן אפשר לעצור הרצה ולהמשיך אותה מאוחר יותר. הרכיב רץ ב-Nodaro Cloud, והתקנה באירוח עצמי מריצה אותו דרך החיבור שלה ל-Nodaro Cloud.

### עצירת הרצה
הנתיב `POST /v1/generate-video-pro/:jobId/stop` עוצר בצורה מסודרת הרצה בסטטוס `processing`:

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

התגובה היא `{ "jobId": "…", "stopping": true }`. המשיכו לבדוק את הסטטוס של המשימה: היא מסתיימת בסטטוס `completed`, כש-`output_data.pro.stopped` הוא `true`, ועם `stoppedAtSegment`. משימה שעדיין בסטטוס `pending` מבוטלת במקום זאת, עם החזר מלא.

### המשך הרצה
הנתיב `POST /v1/generate-video-pro/continue` מתחיל **משימה חדשה** ממשימה שהסתיימה. הנתיב משתמש שוב בתוכנית של משימת האב ובכל מקטע שנמסר לפני `fromSegment`, ויוצר מחדש מהנקודה הזו:

```json
{ "fromJobId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d", "fromSegment": 4 }
```

- השדה `fromSegment` נספר מ-1. כברירת מחדל, זה המקטע הראשון שלא נמסר.
- משימת האב צריכה להיות גמורה: נעצרה, נכשלה אחרי שלפחות מקטע אחד נמסר, או הסתיימה בהצלחה. ערך מפורש ב-`fromSegment`, בהרצה שהסתיימה בהצלחה, יוצר מחדש את הסוף שלה.
- משלמים רק על המקטעים שנוצרים מחדש, ועוד התשלום הקבוע של Video Pro.
- הנתיב מכבד את הכותרת `Idempotency-Key`, ולכן בקשה שנשלחת שוב לא מתחילה משימה שנייה.

התגובה היא `{ jobId, continuedFromJobId, fromSegment, segmentCount }`. בדקו את הסטטוס של ה-`jobId` החדש מדי כמה שניות.

**curl**

```bash
curl -s -X POST https://app.nodaro.ai/v1/generate-video-pro/$JOB_ID/stop \
  -H "Authorization: Bearer $NODARO_API_KEY"

curl -s -X POST https://app.nodaro.ai/v1/generate-video-pro/continue \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 4c1f0a7e-2b3d-4e5f-8a9b-0c1d2e3f4a5b" \
  -d "{\"fromJobId\": \"$JOB_ID\", \"fromSegment\": 4}"
```

**TypeScript SDK**

```ts
await client.videoPro.stop(jobId)
const { data } = await client.jobs.getStatus(jobId) // completes with a partial video

const { jobId: childId } = await client.videoPro.continueRun(jobId, { fromSegment: 4 })
```

**CLI**

```bash
nodaro video-pro stop 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
nodaro video-pro continue 9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d --from-segment 4 --watch
```

שני הנתיבים מחזירים `404` למשימה שלא שייכת לכם, ו-`400` למשימה שהיא לא הרצה של Video Pro.

### אומדן מחיר להרצה
הנתיב `POST /v1/credits/video-pro-estimate` מחזיר אומדן מחיר להרצה של Video Pro, בלי ליצור משימה ובלי שריון קרדיטים:

```json
{ "provider": "gemini-omni-flash", "resolution": "720p", "duration": 12, "renderMethod": "keyframes", "segmentMode": "short" }
```

בתצורה לדוגמה אחת, התגובה היא `{ "data": { "credits": 760, "upperBound": true } }`. בדקו את התגובה בפועל כדי לקבל את המחירים העדכניים.

<TypeTable
type={{
provider: { type: 'string', description: 'מודל הווידאו.', required: true },
resolution: { type: 'string', description: 'הרזולוציה.', default: '720p' },
duration: { type: 'integer', description: 'האורך הכולל בשניות, מ-1 עד 3600.', default: '8' },
aspectRatio: { type: 'string', description: 'יחס הגובה־רוחב.' },
renderMethod: { type: 'string', description: 'הערך extend או keyframes.' },
anchorMode: { type: 'string', description: 'הערך upfront, progressive או none.' },
contextTailSec: { type: 'number', description: 'מ-2 עד 15 שניות.' },
segmentMode: { type: 'string', description: 'הערך short, long או max. אי אפשר לשלב אותו עם preferredSegmentSec או עם segmentDurations.' },
preferredSegmentSec: { type: 'integer', description: 'מ-4 עד 15 שניות.' },
segmentDurations: { type: 'integer[]', description: 'בין 1 ל-24 אורכי מקטעים מפורשים, כל אחד מ-1 עד 30 שניות.' },
planOnly: { type: 'boolean', description: 'אומדן מחיר לשלב התכנון בלבד.' },
}}
/>

- כש-`segmentMode` הוא `short` או `long`, ההרצה משייכת קודם פעולות שלמות לקטעים של המקור, והערך `upperBound: true` אומר שהסכום הוא תקרת השריון לפני התכנון. החיוב הסופי נקבע לפי התוכנית בפועל.
- אומדן `planOnly` מכסה את התשלום על התכנון ומחזיר `upperBound: false`. אפשר לשלוח בחזרה את ה-`sourceSegmentDurations` ואת ה-`planCheckpoint` שלו בתור `sourceSegmentDurations` ו-`seedPlan`, עם אותו מצב ואותן הגדרות.

בדף [יצירת וידאו Pro](https://nodaro.ai/docs/nodes/video/generate-video-pro) מוסבר איך החלוקה למקטעים עובדת ומה כל הגדרה עושה.

## שאלות נפוצות

### מהי משימה ב-API של Nodaro?

משימה היא יחידת יצירה אחת ב-Nodaro, כגון תמונה אחת, רינדור אחד של סרטון או קטע דיבור אחד. בקשת POST /v1/<node-type>‎ מחזירה מזהה משימה, והרצת תהליך יוצרת משימה אחת לכל רכיב AI שהיא מריצה.

### באיזו תדירות כדאי לבדוק את הסטטוס של משימת Nodaro?

כדאי לבדוק את הסטטוס של משימת Nodaro כל 2–5 שניות. משימה משנה מצב בתוך שניות, לא בתוך אלפיות שנייה. כדי לבדוק את המצב של משימות רבות, השתמשו בנתיבים GET /v1/jobs/status או POST /v1/jobs/batch-status, שמחזירים עד 100 משימות בקריאה אחת.

### מה המשמעות של הסטטוס pending_review?

הסטטוס pending_review אומר שהפריסה מעכבת את התוצאה לבדיקה של אדם לפני שהיא משוחררת. המשימה עדיין בעיצומה, והקרדיטים שלה נשארים משוריינים. המשיכו לבדוק את הסטטוס; בסוף המשימה מסתיימת בסטטוס completed, failed או cancelled.

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

כדי לדעת אם הקרדיטים על משימה שנכשלה הוחזרו, בדקו את השדה credit_status בנתיבים GET /v1/jobs/:id או GET /v1/jobs/:id/status. הערך שלו הוא reserved, committed או refunded. על יצירה שמסנן בטיחות או מדיניות של פריסה חסמו תמיד מקבלים החזר.

### איך יודעים כמה משימה עלתה בפועל?

השדה credits_charged בנתיבים GET /v1/jobs או GET /v1/jobs/:id מציין כמה המשימה עלתה אחרי החיוב הסופי של השריון שלה, כולל השלבים שהיא הריצה. הסכום הזה יכול להיות נמוך מהשריון. הערך הוא null כל עוד השריון של המשימה עצמה עדיין פתוח.

### האם אפשר לדרג משימה או לסמן אותה כמועדפת דרך ה-API?

כן. הנתיב PUT /v1/jobs/:id/rating נותן לאחת מהמשימות שלכם את הדירוג good או bad, או מוחק אותו עם null, והנתיב POST /v1/gallery/favorite מסמן משימה כמועדפת או מסיר את הסימון. הנתיב GET /v1/jobs מסנן לפי שניהם עם הפרמטרים rating ו-favorited.
