מודלים וקרדיטים
רשימת מודלי ה-AI שמופע של Nodaro מציע, קריאת יתרת הקרדיטים, בדיקת המחיר של מודל לפני ההרצה וקריאת התוכניות והמנוי שלכם.
client.models מחזיר את קטלוג מודלי ה-AI שמופע של Nodaro מציע, והמשאב client.credits מחזיר את יתרת הקרדיטים שלכם ואת המחיר של כל מודל. המשאב client.billing מחזיר את התוכניות שנמכרות ואת המנוי שלכם. השתמשו בהם יחד כדי להראות למשתמשים אילו מודלים הם יכולים לבחור, וכמה עולה כל הרצה. המתודות קוראות לנקודות הקצה שבדף ה-API קרדיטים. מחירים ויתרות קיימים ב-Nodaro Cloud; בהתקנות באירוח עצמי של מהדורת Community ושל מהדורת Business אין מערכת קרדיטים. ראו את הדף קרדיטים.
מתודות
| מתודה | מה היא עושה |
|---|---|
models.list(opts?) | רשימת המודלים, מקובצים לפי סוג ולפי יצרן |
credits.balance() | קריאת יתרת הקרדיטים שלכם והרמה שלכם |
credits.modelCosts(ids) | בדיקת המחיר בקרדיטים של עד 50 מודלים או וריאנטים |
credits.transactions(options?) | קריאת תנועות הקרדיטים שלכם, עמוד אחד בכל פעם |
credits.usageSummary(options?) | סיכום השימוש שלכם בקרדיטים בתקופה מסוימת, בשביל מסך חיוב |
credits.history(options?) | קריאת כל תנועה ביתרה שלכם, עמוד אחד בכל פעם |
credits.exportHistory(filters?) | ייצוא כל ההיסטוריה המסוננת כקובץ CSV |
credits.claimWelcomeOffer(input?) | מימוש הטבת ההצטרפות באפליקציית ווב של צד ראשון |
credits.markWelcomeOfferSeen() | רישום שהחלון הקופץ של הטבת ההצטרפות הוצג |
billing.plans() ועוד | קריאת התוכניות וחבילות הקרדיטים שנמכרות, המנוי שלכם ואופן החיוב של הפריסה. באפליקציית צד ראשון, גם הרכישות, החשבוניות, הכרטיס, הטעינה האוטומטית והתשלום |
client.models
models.list(opts?)
מחזירה את קטלוג המודלים (GET /v1/models), מקובץ לפי סוג (תמונה, וידאו, אודיו) ולפי יצרן. לכל מודל מופיעים היכולות שלו, המחירים שלו בקרדיטים ב-Nodaro Cloud ועצות פרומפט קצרות. נקודת הקצה ציבורית, והשרת שומר את התשובה במטמון למשך 5 דקות. כלי ה-MCP list_models מחזיר את אותם נתונים.
list(opts?: {
kind?: "image" | "video" | "audio"
mode?: string
family?: string
featuredOnly?: boolean
}): Promise<ModelsListResult>מאפיין
סוג
const catalog = await client.models.list({ kind: "video", mode: "i2v" })
for (const section of catalog.sections) {
for (const family of section.families) {
for (const model of family.models) {
console.log(family.family, model.id, model.durations, model.pricing?.[0]?.credits)
}
}
}התוצאה כוללת את השדה sections, עם מקטע אחד לכל סוג ובכל מקטע families של מודלים; את השדה recommendations, רשימות של מזהי מודלים לשימושים נפוצים; ואת השדה totalModels. לכל מודל יש השדות האלה:
| שדה | סוג | תיאור |
|---|---|---|
id | string | מזהה המודל, לפרמטר provider בהרצה של רכיב. |
label, description | string | שם התצוגה ותיאור קצר. |
modes | string[] | מה המודל עושה, כגון t2i, i2i, t2v או i2v. |
useCases | string[] | שימושים שהמודל מתאים להם. |
aspectRatios, resolutions, qualities, durations | מערכים | הערכים שהמודל מקבל, איפה שהם רלוונטיים. |
features | string[] | יכולות נוספות. |
pricing | { identifier, credits, note? }[] | המחיר בקרדיטים של כל וריאנט: המחיר שלפיו הרצה מחויבת, אותו מספר שמופיע על הכפתור הרצה. ב-Nodaro Cloud בלבד. |
featured | boolean | האם המודל מומלץ. |
promptTips | string[] | עצות קצרות לכתיבת פרומפטים למודל. |
doctrineCovered | boolean | הערך הוא true רק כשיש ל-Nodaro הכוונה לכתיבת פרומפטים, ממקורות מתועדים, למשפחה של המודל. הציגו תג של ״הכוונת היצרן״ רק כשהערך הוא true. |
maker | { id, name } | החברה שיצרה את המודל. השדה id קבוע, אחד לכל חברה, כגון "google" או "black-forest-labs", כך שאפשר להשתמש בו כמפתח לקבצים הגרפיים שלכם. שרת חדש יותר יכול להוסיף יצרנים, ולכן טפלו גם במזהה שאתם לא מכירים. היצרן הוא לא תמיד ה-family שהמודל מקובץ תחתיו. |
logoUrl | string | null | הלוגו הרשמי של היצרן, קובץ SVG ב-CDN המדיה של המופע עצמו. הערך הוא null כשהמופע לא מפרסם לוגו ליצרן הזה: הציגו במקומו את שם היצרן או את האות הראשונה שלו. השתמשו בכתובת כמו שהיא, כי לוגו שהוחלף מגיע בכתובת חדשה. כלי ה-MCP משמיט אותו. |
שרת מגרסה ישנה יותר משמיט את maker ואת logoUrl.
כדי להציג את הלוגואים של היצרנים בלי הקטלוג, קראו ל-GET /v1/model-makers. נקודת הקצה מחזירה { makers: [{ id, name, logoUrl }] }, עם כל יצרן שהפלטפורמה מכירה, ועם אותם שדות כמו בקטלוג. היא ציבורית, והתשובה נשמרת במטמון למשך 5 דקות. ראו בדף ה-API גילוי מודלים.
for (const section of catalog.sections)
for (const family of section.families)
for (const m of family.models)
console.log(m.id, m.maker?.name ?? family.family, m.logoUrl ?? "(no mark)")אותו קטלוג מופיע בחלק מודלים של התיעוד. לעצות על בחירת המודל המתאים, ראו את המדריך בחירת מודל.
client.credits
credits.balance()
מחזירה את יתרת הקרדיטים שלכם ואת הרמה שלכם (GET /v1/user/credits). כשאף משתמש לא מחובר, המתודה זורקת UnauthorizedError.
balance(): Promise<UserBalance>const balance = await client.credits.balance()
console.log(`${balance.total} credits (${balance.effectiveTier})`)| שדה | סוג | תיאור |
|---|---|---|
total | number | הקרדיטים שאפשר להוציא עכשיו. |
subscription | number | קרדיטי המנוי שנשארו החודש. בכל חודש הם מתאפסים ל-monthlyAllocation, גם בתוכנית שנתית, וקרדיטים שלא הוצאו לא עוברים לחודש הבא. |
topup | number | קרדיטים שקניתם בנפרד. |
dailySpent | number | הקרדיטים שהוצאו היום. |
dailyLimit | number | null | תקרת ההוצאה היומית, או null כשאין תקרה. |
monthlyAllocation | number | הקרדיטים שהתוכנית מעניקה בכל חודש, גם בחיוב חודשי וגם בחיוב שנתי. |
tier | string | רמת המנוי השמורה, כגון "free" או "pro". |
effectiveTier | string | הרמה שחלה בפועל. הערך "payg" פירושו תשלום לפי שימוש: אין מנוי, אבל נקנו קרדיטים, ואז כל המודלים פתוחים, אין סימן מים ואין תקרה יומית. |
features | Record<string, unknown> | היכולות של הרמה. |
periodEnd | string | null | סוף תקופת החיוב הנוכחית, כתאריך בפורמט ISO 8601. בתוכנית שנתית הוא רחוק שנה, אבל קרדיטי המנוי עדיין מתאפסים בכל חודש. |
appCreditsAllowance | number | קרדיטים שהרווחתם מהרצת אפליקציות, במסלול החינמי. |
freeGrantState | FreeGrantState | מה מצב מענק ההרשמה החינמי: "unclaimed", "granted", "withheld" או "revoked". הערך "withheld" פירושו שהחשבון עובד, אבל המענק לא נכנס, ולכן הציגו את שלבי ההפעלה. השדה לא מופיע כשבפריסה אין מענק הרשמה. |
freeGrantNotice | "browser_unmeasured" | רק עם "withheld", כשבקשת המענק לא כללה שום סימן מהדפדפן. האפליקציה שלכם יכולה לומר שקרדיטים חינם דורשים דפדפן רגיל וטעינה מחדש של הדף. |
welcomeOffer | WelcomeOfferState | מופיע רק כל עוד הטבת ההצטרפות מופעלת בפריסה. כשהשדה לא מופיע, אין חלון קופץ, אין באנר ואין חסימה. ראו את הסעיף claimWelcomeOffer(). |
externalWallet | { available: number | null } | מופיע כשהפריסה משתמשת בארנק חיצוני משותף. הערך null פירושו שהסכום לא זמין. אל תציגו את total במקומו. ראו את הדף ארנקים חיצוניים. |
כשמחליטים מה להציג, עדיף להסתמך על effectiveTier ולא על tier.
credits.modelCosts(ids)
בודקת בקריאה אחת את המחיר בקרדיטים של מודלים ושל הווריאנטים שלהם (POST /v1/credits/model-costs). המתודה בודקת עד 50 המזהים הראשונים.
modelCosts(ids: string[]): Promise<{
data: Record<string, number>
missing: string[]
errors: string[]
estimates?: string[]
errorCodes?: Record<string, { code: string; message: string }>
}>מאפיין
סוג
const { data, missing } = await client.credits.modelCosts([
"nano-banana-pro",
"nano-banana-pro:4K",
"seedance-2-fast:8s:720p",
])
console.log(data["nano-banana-pro:4K"])
if (missing.length) console.warn("No price for:", missing)dataממפה כל מזהה שיש לו מחיר למחיר שלו בקרדיטים.missingמפרט מזהים שאין להם מחיר. הציגו עבורם מקף.errorsמפרט מזהים שהבדיקה שלהם נכשלה. שאר המחירים בכל זאת מגיעים.estimatesמפרט את המזהים ב-dataשהמספר שלהם הוא אומדן, ולא מחיר קבוע. אלה מפתחות מחיר של קריאות LLM שמחויבות לפי השימוש. הציגו אותם כ-≈N. כשאין כאלה, השדה לא מופיע.errorCodesמסביר למה לכל מזהה ב-errorsאין מחיר. כרגע הקוד הואllm_model_unpriced: מודל בלי תעריף בשירות שאמור להריץ אותו, ולכן אי אפשר להריץ אותו. כש-errorsריק, השדה לא מופיע.
המזהים של כל מודל מופיעים בשדה pricing של models.list() ובדף של כל מודל. הגדרות כגון איכות, רזולוציה ואורך משנות את המחיר, ולכן ציינו את הווריאנט שההרצה תשתמש בו. המחיר נבדק שוב כשההרצה מתחילה, ולכן הקריאה הזו רק מציגה אותו מראש.
מודלי דיבור מתומחרים לפי אורך הטקסט. המזהה שלהם לכל 100 תווים, או חלק מהם, הוא <model>:per-100-chars, למשל elevenlabs-v4:per-100-chars. בהתקנה שלא מתמחרת דיבור לפי אורך, המזהה הזה מופיע ב-missing, כך שהתשובה גם מראה לפי איזה כלל השרת גובה.
בקשה מתומחרת כמכלול ומעוגלת פעם אחת. לכן המחיר המדויק של בקשה עם N יחידות של 100 תווים, או חלק מהן, הוא המזהה <model>:per-100-chars:<N>u, כש-N נע מ-8 ועד התקרה של המודל לבקשה. מכפלה של N במחיר היחידה יכולה לצאת גבוהה יותר. אותה צורת מזהה נותנת מחיר לכל הרצה שמחויבת לפי יחידה: המזהה <row>:<N>u הוא המחיר המדויק של N יחידות של שורת המחיר הזו, למשל apply-edl:4u, trim-video:5u, ltx-2.3-pro-retake:per-second:2.5u או elevenlabs-dubbing:3u. להמרה שלמה של רכיב משנה קול Pro יש מזהה voice-changer-pro:<slot>,<slot>,…, והפונקציה voiceChangerProQuoteCreditId(slots) מ-@nodaro/shared בונה אותו. ראו בדף ה-API מחירים מדויקים להרצות שמתומחרות לפי יחידה.
לקריאת LLM אין מחיר קבוע. היא מחויבת לפי הטוקנים שהיא השתמשה בהם בפועל, בתעריף של המודל בשירות שהריץ אותה. מפתח המחיר שלה הוא <feature>:<model>, ועוד :direct כשהקריאה רצה ב-API של הספק עצמו, והפונקציה llmPriceKey מ-@nodaro/shared/llm-models בונה אותו. התשובה היא אומדן של קריאה טיפוסית:
import { llmPriceKey } from "@nodaro/shared/llm-models"
const key = llmPriceKey("llm-chat", "claude-fable-5") // "llm-chat:claude-fable-5"
const { data, estimates } = await client.credits.modelCosts([key])
const shown = estimates?.includes(key) ? `~${data[key]}` : String(data[key])מפתח של קריאה שמחויבת לפי השימוש, כשהוא מופיע ב-missing, פירושו שהשרת לא מתמחר קריאות LLM לפי מודל, ולכן אל תציגו לו מחיר. הנתיב GET /v1/credits/model-cost?model=<id> עונה על מזהה אחד בצורה { model, creditCost, estimate?: true }. ראו בדף ה-API קריאות LLM, ואת הסעיף איך מחויבות קריאות LLM בדף קרדיטים.
credits.transactions(options?)
מחזירה עמוד אחד מתנועות הקרדיטים שלכם, מהחדש לישן (GET /v1/credits/transactions). ב-Nodaro Cloud בלבד: בהתקנה באירוח עצמי הנתיב מחזיר 404.
transactions(options?: { limit?: number; cursor?: string }): Promise<CreditTransactionsPage>מאפיין
סוג
העמוד הוא { data: CreditTransaction[], nextCursor }. השדה nextCursor הוא null כשאין עוד שורות.
| שדה | סוג | תיאור |
|---|---|---|
id | string | מזהה התנועה. |
created_at | string | תאריך בפורמט ISO 8601. |
credits_charged | number | null | כמה ההרצה עלתה, אחרי החיוב הסופי. הערך יכול להיות נמוך מהשריון, הוא 0 כשהקרדיטים המשוריינים הוחזרו, והוא null כל עוד השריון עדיין פתוח. |
credits_reserved | number | null | השריון שנלקח כשההרצה התקבלה. הערך הזה אף פעם לא משתנה. |
credits_used | number | null | אותו שריון, בשם המקורי שלו, שנשמר בשביל אינטגרציות קיימות. עדיף להשתמש ב-credits_charged. |
action | string | null | המודל או הפעולה שהקרדיטים שולמו עליהם. |
status | string | null | "reserved", "committed" או "refunded". |
metadata | Record<string, unknown> | פרטי החיוב של ההרצה עצמה. |
payer | "user" | "workspace" | הערך "workspace" פירושו שהתשלום ירד מתקציב של כיתה או של צוות, ולא מהיתרה שלכם. |
workspaceId | string | null | סביבת העבודה שמשלמת, כשהשדה payer הוא "workspace". |
איזה סכום לקרוא. קודם משוריינים קרדיטים להרצה, ואחר כך מגיע החיוב הסופי שלה: נגבה עליה כל השריון או חלק ממנו, והשאר חוזר ליתרה שלכם. כדי לחשב את ההוצאות שלכם, סכמו את credits_charged. ראו את דף ה-API קרדיטים.
let cursor: string | undefined
let spent = 0
do {
const page = await client.credits.transactions({ limit: 50, cursor })
for (const t of page.data) spent += t.credits_charged ?? 0
cursor = page.nextCursor ?? undefined
} while (cursor)
console.log(`${spent} credits charged`)credits.usageSummary(options?)
מחזירה את השימוש בקרדיטים בתקופה מסוימת, מסוכם כמו שמסך חיוב מציג אותו (GET /v1/credits/usage-summary). המתודה סופרת רק את הכסף האישי שלכם: הרצה שסביבת עבודה שילמה עליה לא נכללת. ב-Nodaro Cloud בלבד.
usageSummary(options?: { from?: string; to?: string; bucket?: "day" | "week" | "month" }): Promise<UsageSummary>מאפיין
סוג
בפריסה שבה חשבון חיוב אחד משלם על כל המשתמשים, רק הסשן של חשבון החיוב עצמו יכול לקרוא למתודה. קריאה עם האסימונים שלו נכשלת עם ForbiddenError והקוד payer_balance_jwt_only.
| שדה | סוג | תיאור |
|---|---|---|
period | { from, to, bucket } | התקופה, כפי שהשרת קיבל אותה. |
totals | UsageSummaryTotals | { used, purchased, granted, refunded, runs, avgPerRun }. פירוט בהמשך. |
mostUsed | UsageByModel | null | המודל עם ההוצאה הגבוהה ביותר, או null כשאין הרצות. |
byModel | UsageByModel[] | { model, provider, credits, runs, share }, ממוינים לפי ההוצאה. השדה share הוא החלק מתוך used, בין 0 ל-1. |
byCategory | UsageByCategory[] | { category, credits, runs }, כשהשדה category הוא "image", "video", "audio" או "other". |
overTime | UsageOverTime[] | שורה אחת לכל יחידת זמן, כולל יחידות ריקות, מהישן לחדש: { bucket, used, purchased, runs }. השדה bucket הוא היום לפי UTC ("2026-10-26"), יום שני של השבוע או החודש ("2026-10"). יחידת הזמן הראשונה יכולה להיות שבוע חלקי או חודש חלקי. |
bySession, byWorkflow | UsageByGroup[] | כמה עלה כל סשן או כל תהליך, ממוינים לפי ההוצאה: { id, name, tool, credits, runs, models, lastAt }. השדה name הוא null כשאין לסשן או לתהליך שם, או כשהוא כבר לא קיים. השדה tool מופיע רק בסשן. |
truncated | boolean | הערך הוא true כששליפת נתונים בשרת הגיעה לתקרה של 5,000 שורות, ולכן המספרים נמוכים מדי. בקשו תקופה קצרה יותר. |
partial | boolean | הערך הוא true כששליפה משנית של נתונים נכשלה, ולכן קיבוץ מסוים חסר או בלי שמות. הסכומים הכוללים עדיין מלאים. |
ב-totals:
- השדה
usedמסכם את החיוב של כל הרצה. הרצה שעדיין רצה נספרת לפי השריון שלה, והרצה שהקרדיטים עליה הוחזרו לא נספרת. - השדה
purchasedכולל את החבילות, את הטעינות ואת הקצאות המנוי. - השדה
grantedהוא הקרדיטים החינמיים, פחות מענקים שנלקחו בחזרה. - השדה
refundedהוא מה שחזר על הרצה שהקרדיטים עליה הוחזרו, או מ-Stripe. החלק של השריון שמשתחרר כשהחיוב הסופי של הרצה נמוך ממנו הוא לא החזר. - השדה
runsסופר את ההרצות שחויבו או שעדיין רצות. השדהavgPerRunהואusedחלקיruns, עם ספרה אחת אחרי הנקודה.
const s = await client.credits.usageSummary({ bucket: "week" })
console.log(s.totals.used, "credits used;", s.mostUsed?.model, "most used")
for (const w of s.overTime) console.log(w.bucket, w.used)credits.history(options?)
מחזירה עמוד אחד מתוך כל התנועות ביתרה שלכם, מהחדש לישן (GET /v1/credits/history): הרצות, רכישות, מענקים, החזרים, תיקונים ופקיעות תוקף, כל אחת עם היתרה שאחריה. המתודה transactions() מחזירה רק הרצות, ואילו history() מחזירה את הדוח המלא שמסך חיוב מציג. ב-Nodaro Cloud בלבד, ובפריסה עם חשבון חיוב אחד חל אותו כלל כמו ב-usageSummary().
history(options?: CreditHistoryOptions): Promise<CreditHistoryPage>מאפיין
סוג
העמוד הוא { data: CreditHistoryEntry[], nextCursor }. בעמוד האחרון השדה nextCursor הוא null.
| שדה | סוג | תיאור |
|---|---|---|
id | string | המזהה של השורה. |
at | string | מתי התנועה קרתה, כתאריך בפורמט ISO 8601. |
kind | CreditHistoryKind | סוג התנועה. הערך "app" מציין קרדיטים שהרווחתם מאפליקציה שפורסמה או ששילמתם על אפליקציה כזו. הערך "adjustment" מציין תיקון של מנהל וכל דבר אחר. |
source | string | המונח שהרשומה עצמה משתמשת בו, כגון usage, one_time_purchase, subscription_renewal, signup_grant, refund, app_earnings או expiry. |
amount | number | התנועה, עם סימן: השריון של הרצה שלילי, ורכישה חיובית. |
balanceAfter | number | היתרה מיד אחרי התנועה. |
pool | "subscription" | "topup" | "mixed" | איזה חלק של היתרה השתנה. |
description | string | null | ההערה של הרשומה. |
model, provider | string | null | המודל שרץ והספק שלו, בשורה שקשורה למשימה. |
charge | number | null | החיוב של המשימה, רק בשורת השריון שלה, כלומר בשורה של השריון שנלקח כשההרצה התקבלה. הערך הוא החיוב הסופי, השריון כל עוד ההרצה פתוחה, או 0 אחרי שהקרדיטים הוחזרו. בכל שורה אחרת הערך הוא null, ולכן סכימה של charge סופרת כל משימה פעם אחת. כדי לדעת כמה הוצאתם, בדקו את השדה הזה, לא את amount. |
status | string | null | לצד charge: "reserved", "committed" או "refunded". |
job | CreditHistoryJob | null | בשורה שקשורה למשימה: { id, type, status, startedAt, completedAt, durationMs, workflowId, sessionId }. השדה type ושאר השדות הם null כשהמשימה כבר לא קיימת. |
receiptUrl | string | null | הקבלה של Stripe, ברכישה שיש לה קבלה. |
const page = await client.credits.history({ kind: "usage", limit: 50 })
for (const e of page.data) console.log(e.at, e.model, e.charge ?? e.amount, "→", e.balanceAfter)credits.exportHistory(filters?)
מחזירה את כל ההיסטוריה המסוננת כטקסט CSV (GET /v1/credits/history?format=csv). יש בה אותם שדות ומסננים כמו ב-history(), שורה אחת לכל תנועה, מהחדש לישן, בלי חלוקה לעמודים. יש בה 5,000 שורות לכל היותר, וכשהרשימה נקטעת, השורה האחרונה מציינת זאת: צמצמו את הטווח של from ו-to כדי לקבל את השאר.
exportHistory(filters?: CreditHistoryFilters): Promise<string>const csv = await client.credits.exportHistory({ from: "2026-10-01T00:00:00Z" })
const href = URL.createObjectURL(new Blob([csv], { type: "text/csv" }))credits.claimWelcomeOffer(input?)
רושמת בפעולה אחת את ה״כן״ של המשתמש להטבת ההצטרפות (POST /v1/credits/welcome-offer/claim). המתודה רושמת את ההסכמה לקבלת מיילים שיווקיים, ואז מבקשת את מענק ההרשמה החינמי עם ההסכמה הזו. בדיקות השימוש לרעה עדיין מכריעות, ולכן בדקו את grant. בחשבון שהמענק שלו כבר הוכרע, רק ההסכמה נרשמת. ב-Nodaro Cloud בלבד: בהתקנה באירוח עצמי הנתיב מחזיר 404.
claimWelcomeOffer(input?: WelcomeOfferClaimInput): Promise<WelcomeOfferClaimResult>המתודה הזו דורשת סשן מחובר בדפדפן, מ-supabaseAuth(), כי ההסכמה היא בחירה של אדם. קריאה עם אסימון API או עם אסימון של אפליקציית OAuth נדחית עם 403. כל עוד ההטבה כבויה בפריסה, הקריאה נדחית עם 409 welcome_offer_disabled, ולכן הציגו את ההטבה רק כש-balance().welcomeOffer קיים.
הטיפוס WelcomeOfferClaimInput הוא האובייקט SignupKeys שהפונקציה collectSignupKeys() מחזירה, ועוד sourceApp, מזהה קצר (slug) של האפליקציה שלכם, עד 40 אותיות קטנות, ספרות ומקפים. מזהה פגום נשמר כאילו לא נשלח, ואף פעם לא נדחה. הקלט מקבל גם locale, שפת הממשק שבה המשתמש ענה. זה המזהה של שפה ש-Nodaro מציע, כגון "en", "ja" או "pt-BR". ההתאמה מדויקת ותלויה ברישיות, ולכן "en-US" או "pt-br" נשמרים כאילו לא נשלחו. השפה נרשמת עם ההסכמה, כשפה של ההסכמה האחרונה.
| שדה | סוג | תיאור |
|---|---|---|
consent | "granted" | ההסכמה לקבלת מיילים נרשמה. |
grant | FreeGrantState | הערך "granted": המענק נכנס עכשיו או קודם. הערך "withheld": בדיקות השימוש לרעה דחו אותו. הערך "revoked": המענק נלקח בחזרה בעבר. הערך "unclaimed": שום דבר לא זז, ולכן התייחסו לזה ככישלון ואפשרו למשתמש לנסות שוב. |
credits | number | מספר הקרדיטים של המענק, אותו מספר כמו ב-balance().welcomeOffer.credits. מענק משלים את קרדיטי המנוי עד המספר הזה. הוא לא מתווסף עליהם. |
לטיפוס WelcomeOfferState יש שלושה שדות: popupSeen (החלון הקופץ החד־פעמי הוצג), consentPending (הקרדיטים כבר נמצאים בחשבון, אבל ההסכמה לקבלת מיילים עדיין חסרה) ו-credits (מה שמימוש ההטבה מעניק). הציגו בהטבה את המספר שב-credits במקום מספר קבוע, כי המספר נקבע לפי השרת.
credits.markWelcomeOfferSeen()
רושמת שהחלון הקופץ החד־פעמי של הטבת ההצטרפות הוצג (POST /v1/credits/welcome-offer/seen), כך שהשדה welcomeOffer.popupSeen הופך ל-true בכל אפליקציה. קריאה נוספת לא משנה כלום. קריאה שנכשלה פירושה רק שהחלון הקופץ עשוי להופיע פעם נוספת, ולכן אפשר להתעלם משגיאות. חלים אותם כללים כמו ב-claimWelcomeOffer().
markWelcomeOfferSeen(): Promise<{ ok: true }>import { collectSignupKeys } from "@nodaro/sdk/signup-signals"
const { welcomeOffer } = await client.credits.balance()
if (welcomeOffer && !welcomeOffer.popupSeen) {
showPopup({ credits: welcomeOffer.credits }) // the server's figure, never a constant
void client.credits.markWelcomeOfferSeen().catch(() => {})
}
// On "Yes":
const keys = await collectSignupKeys()
const { grant, credits } = await client.credits.claimWelcomeOffer({ ...keys, sourceApp: "my-app", locale: "en" })
if (grant === "granted") showToast(`Your ${credits} free credits are ready`)client.billing
client.billing קורא את התוכניות והמחירים שנמכרים, את המנוי של מי שקורא למתודות ואת אופן החיוב של הפריסה. באפליקציית צד ראשון שמחוברת עם הסשן של המשתמש עצמו (supabaseAuth), המשאב מכסה גם את כל מסך החיוב: רכישות, חשבוניות, הכרטיס השמור, הטעינה האוטומטית והמעבר ל-Stripe Checkout ול-Customer Portal. המתודות שמסומנות לסשן בלבד עונות רק לסשן מחובר. קריאה עם מפתח API או עם אסימון OAuth של אפליקציה נכשלת עם ForbiddenError, ולכן בלקוח כזה הוסיפו במקום זאת קישור לדף החיוב של האפליקציה.
// A pricing screen: works signed out.
const { data: plans, topUps } = await client.billing.plans()
// Mark the plan the signed-in account is on.
const { effectiveTier } = await client.billing.subscription()
const current = plans.find((p) => p.id === effectiveTier) // undefined: pay-as-you-go, or a tier not on sale| מתודה | מה חוזר | הערות |
|---|---|---|
plans() | Promise<BillingPlansResult> | GET /v1/billing/plans. ציבורית: לא צריך פרטי גישה, וכל מי שקורא לה מקבל את אותה תשובה. מחזירה { data: BillingPlan[], topUps, topUpRange }. ב-Nodaro Cloud בלבד: במופע באירוח עצמי היא זורקת NotFoundError. בפריסה שלא מוכרת למשתמשים שלה היא זורקת ForbiddenError. כשאי אפשר לקרוא את המחירים לרגע, היא זורקת NodaroError עם סטטוס 503. |
subscription() | Promise<BillingSubscriptionResult> | GET /v1/billing/subscription. מחזירה { data: BillingSubscription | null, effectiveTier }. השדה data הוא null כשלחשבון אף פעם לא היה מנוי. השדה effectiveTier הוא הרמה שלפיה נקבע מה החשבון מקבל: בדרך כלל id של תוכנית, "payg" לקרדיטים שנקנו בלי מנוי, או רמה שלא נמכרת, כגון "enterprise". דורשת סשן בדפדפן, אסימון API אישי בלי מגבלת תהליכים או אסימון OAuth של אפליקציה. ב-Nodaro Cloud בלבד. |
surface() | Promise<BillingSurface> | GET /v1/billing/surface. ציבורית, בכל המהדורות. אם הפריסה מודדת שימוש בכלל (השדה providerId הוא "none" כשהיא לא מודדת), ובאיזו יחידה מוצגות העלויות (displayUnit). |
account() | Promise<BillingAccountSummary | null> | GET /v1/billing/account. השדות plan, balance ו-dailyAllowance של מי שקורא לה, כפי שספק החיוב של הפריסה מדווח עליהם, ביחידה שב-unit. הערך הוא null כשהספק לא הצליח לענות, וזו לא יתרה של אפס. בכל המהדורות. |
purchases() | Promise<BillingPurchase[]> | GET /v1/billing/transactions. לסשן בלבד. רכישות הקרדיטים של החשבון, מהחדש לישן, 50 האחרונות: { id, stripe_transaction_id, type, amount_usd, credits_granted, tier, created_at, receipt_url }. השדה type הוא "subscription", "topup" או "refund", וב-"refund" הערך של credits_granted שלילי. |
invoices() | Promise<BillingDocument[]> | GET /v1/billing/invoices. לסשן בלבד. כל תשלום כמסמך, מהחדש לישן. השדה kind הוא "invoice" בתשלום על מנוי, עם ה-number, ה-pdfUrl וה-url של Stripe. הוא "receipt" בחבילת קרדיטים או בטעינה, עם ה-credits שהוענקו ועם הקבלה ב-url, בלי PDF. החזר הוא קבלה עם status בערך "refunded", וה-amount וה-credits שלה שליליים. השדה status הוא "paid", "open", "void", "uncollectible" או "refunded". |
paymentMethod() | Promise<BillingPaymentMethod> | GET /v1/billing/payment-method. לסשן בלבד. { card, billingDetails }: השדה card הוא { brand, last4, expMonth, expYear } או null, והשדה billingDetails הוא { name, email, country } או null. בחשבון שעוד לא קנה דבר שניהם null, ואף פעם לא חוזרת שגיאה. |
autoRecharge() | Promise<BillingAutoRecharge> | GET /v1/billing/auto-recharge. לסשן בלבד. { enabled, thresholdCredits, amountUsd, failureCount, lastAttemptAt, hasSavedCard }. כשהיתרה יורדת מתחת לסף, הסכום נטען מהכרטיס השמור. |
setAutoRecharge(input) | Promise<BillingAutoRechargeSaved> | PUT /v1/billing/auto-recharge. לסשן בלבד. { enabled, thresholdCredits?, amountUsd? }. כדי להפעיל את הטעינה האוטומטית צריך את שני המספרים: השדה thresholdCredits, מ-100 עד 100,000, והשדה amountUsd, סכום שלם בתוך topUpRange. אחרת המתודה זורקת NodaroError עם סטטוס 400. השמירה מאפסת את מונה הכישלונות. |
checkout(input) | Promise<BillingCheckoutSession> | POST /v1/billing/create-checkout-session. לסשן בלבד. עם הקלט { priceId, mode?, returnPath?, embedded? }, המתודה מחזירה { url }, דף של Stripe Checkout למחיר של תוכנית או לחבילת קרדיטים. שלחו את המשתמש לשם. קודי הנחה חלים על תוכניות בלבד, ורכישת חבילה שהחיוב הסופי שלה הוא 0 לא מעניקה קרדיטים. לתוכנית, כל עוד יש לחשבון מנוי, המתודה זורקת שגיאה עם סטטוס 409: השתמשו במקום זאת במתודה changePlan(). בפריסה שלא מוכרת למשתמשים שלה, המתודה זורקת ForbiddenError עם הקוד self_serve_disabled. |
loadCredits(input) | Promise<BillingLoadSession> | POST /v1/billing/create-load-session. לסשן בלבד. עם הקלט { amountUsd, returnPath?, embedded? }, המתודה מחזירה { url, credits }: דף Checkout שטוען סכום שלם בתוך topUpRange כקרדיטים, באותו תעריף כמו החבילות. השדה credits הוא מה שהטעינה מעניקה. הכרטיס נשמר בשביל הטעינה האוטומטית. |
portal(input?) | Promise<BillingPortalSession> | POST /v1/billing/manage-subscription. לסשן בלבד. עם הקלט { returnPath? }, המתודה מחזירה { url }, דף של Stripe Customer Portal לניהול הכרטיס, כתובת החיוב, החשבוניות וביטול המנוי. לפני הרכישה הראשונה, המתודה זורקת NotFoundError. |
changePlan(input) | Promise<BillingChangePlanResult> | POST /v1/billing/change-plan. לסשן בלבד. עם הקלט { newPriceId }, המתודה מחזירה { subscriptionId, tier }. המתודה מעבירה את המנוי הפעיל למחיר של תוכנית אחרת. בשדרוג, הפרש המחיר על יתרת תקופת החיוב נגבה מיד, והשדרוג נכנס לתוקף רק כשהתשלום הזה מצליח. השדרוג מוסיף את ההפרש בין הקרדיטים החודשיים של שתי התוכניות, פעם אחת בכל תקופת חיוב, וחשבונית שדרוג שהחיוב הסופי שלה הוא 0 לא מוסיפה קרדיטים. מעבר לתוכנית נמוכה יותר נכנס לתוקף מיד: ערך הזמן שנותר מקוזז מהחשבונית הבאה, והקרדיטים הנוכחיים נשארים עד סוף התקופה. מעבר מחודשי לשנתי, או בחזרה, לא מוסיף קרדיטים. בלי מנוי פעיל המתודה זורקת NotFoundError, עם מחיר של חבילה או עם המחיר הנוכחי שגיאה עם סטטוס 400, וכשהמנוי לא פעיל שגיאה עם סטטוס 409. כשהשדרוג מחכה לתשלום שלו, המתודה זורקת NodaroError עם סטטוס 409 והקוד plan_change_payment_required: התוכנית לא משתנה, והשדה details.invoiceUrl הוא הדף של Stripe לתשלום החשבונית. אחרי 5 בקשות לשינוי תוכנית מאותו חשבון בתוך 24 שעות, המתודה זורקת RateLimitedError. ראו בדף ה-API שינוי תוכנית. |
הפרמטר returnPath הוא נתיב ב-origin שלכם, כגון "/billing" או "/settings/credits?tab=history", ש-Stripe מחזיר אליו את המשתמש. הנתיב מתחיל ב-/ אחד, יכול לכלול מחרוזת שאילתה, ואין בו שם מארח או #. התשלום והטעינה מוסיפים למחרוזת השאילתה שלו checkout=success או checkout=cancelled. הפרמטר returnPath גובר על embedded. בלעדיו, משתמשים בדפים של האפליקציה של Nodaro עצמה.
// A billing screen in a first-party app, signed in with supabaseAuth.
const [method, docs, auto] = await Promise.all([
client.billing.paymentMethod(),
client.billing.invoices(),
client.billing.autoRecharge(),
])
// Buy a pack and come back to this screen.
const { url } = await client.billing.checkout({ priceId: pack.priceId!, returnPath: "/settings/credits" })
window.location.assign(url!)השדות של BillingPlan:
| שדה | סוג | תיאור |
|---|---|---|
id | string | "free", "basic", "standard", "pro" או "business". |
name | string | שם התצוגה. |
prices | { monthly, yearly } | null | הערך הוא null במסלול החינמי. השדה monthly הוא { priceId, amount, currency, credits }. השדה yearly מוסיף את perMonth, הסכום השנתי מחולק על פני החודשים שלו. השדה priceId הוא מזהה המחיר ב-Stripe שהמתודות checkout() ו-changePlan() מקבלות, ושהשדה stripe_price_id של המנוי תואם לו. השדה amount הוא ביחידה הראשית של המטבע (12 פירושו 12.00), והשדה currency הוא קוד ISO 4217, כגון "USD". כל אחד מהמחירים יכול להיות null כשאי אפשר למכור אותו כרגע: הציגו אותו כלא זמין, אף פעם לא כחינם. |
prices.*.credits | { amount, per } | null | מה המחיר מעניק, כשהשדה per הוא "month" או "year". מחיר שנתי מעניק את הקרדיטים של התוכנית בכל חודש, כמו מחיר חודשי. |
signupCredits | number | null | המענק החד־פעמי של המסלול החינמי בהרשמה. הערך הוא null בתוכנית בתשלום. |
parallelism | number | כמה רכיבים של תהליך אחד רצים בו־זמנית. |
storageBytes | number | נפח האחסון למדיה שלכם, בבייטים. |
השדה topUps כולל את חבילות הקרדיטים, { id, credits, price, priceId }, מהקטנה לגדולה. השדה id הוא המזהה של החבילה עצמה, כגון "topup-25". השדה price הוא null כשאי אפשר לציין אותו כרגע. השדה priceId הוא מזהה המחיר ב-Stripe בשביל checkout(), והוא null כשהמחיר null. תמיד אפשר לקנות חבילה כטעינה של price.amount דרך loadCredits(). השדה topUpRange, { min, max, currency }, הוא טווח הסכומים השלמים שאפשר לטעון כקרדיטים, באותו תעריף כמו החבילות. על קניית קרדיטים בלי תוכנית, ראו את הדף API בלי מנוי.
הצגת מודלים עם המחירים שלהם
כך בונים תפריט בחירת מודל לרכיב אחד, עם המחיר ליד כל מודל:
const { data: node } = await client.nodes.get("generate-video")
const { data: prices } = await client.credits.modelCosts(node.providers ?? [])
const options = (node.providers ?? []).map((id) => ({
id,
price: prices[id] ?? null, // null: no price on this instance
}))השמיטו את provider בהרצה כדי להשתמש במודל ברירת המחדל של הרכיב. כשמשתמש בוחר מודל, שלחו את המזהה שלו בתור provider ל-client.nodes.runAndWait().
שאלות נפוצות
איך מקבלים מקוד את רשימת המודלים ש-Nodaro מציע?
קראו ל-client.models.list(). המתודה מחזירה כל מודל תמונה, וידאו ואודיו, מקובץ לפי סוג ולפי יצרן, עם המצבים, יחסי הגובה־רוחב, הרזולוציות והאורכים שלו, וב-Nodaro Cloud גם עם המחירים שלו בקרדיטים.
איך בודקים את המחיר של מודל אחד לפני ההרצה?
קראו ל-client.credits.modelCosts עם מזהי המחיר של המודל, כגון nano-banana-pro או nano-banana-pro:4K. השדה data ממפה כל מזהה למחיר שלו בקרדיטים.
איך מקבלים אומדן מחיר לקריאת LLM עם ה-SDK?
בנו את מפתח המחיר עם llmPriceKey(feature, model) מ-@nodaro/shared/llm-models, למשל llm-chat:claude-fable-5, והעבירו אותו ל-client.credits.modelCosts. המספר הוא אומדן של קריאה טיפוסית, והוא מופיע ב-estimates, ולכן הציגו אותו כ-≈N.
איך בודקים את יתרת הקרדיטים עם ה-SDK?
קראו ל-client.credits.balance(). השדה total הוא מספר הקרדיטים הזמינים, בחלוקה לקרדיטי מנוי ולקרדיטי טעינה.
איך מחשבים עם ה-SDK כמה עלו ההרצות שלי?
עברו על העמודים של client.credits.transactions() עם הערך nextCursor של כל עמוד, וסכמו את credits_charged. השריון שנלקח קודם בשביל ההרצה, credits_reserved, הוא לא מה ששילמתם.
איך מציגים את התוכניות והמחירים של Nodaro באפליקציה שלי?
קראו ל-client.billing.plans(). המתודה לא דורשת התחברות, ומחזירה כל תוכנית עם המחיר החודשי והשנתי שלה ועם הקרדיטים שלה, וגם את חבילות הקרדיטים. רכישה דורשת את הסשן המחובר של המשתמש עצמו, דרך client.billing.checkout().
איך בונים עם ה-SDK מסך של שימוש או של היסטוריית חיוב?
קראו ל-client.credits.usageSummary() כדי לקבל את הסכומים של תקופה, לפי מודל, קטגוריה, סשן ותהליך. קראו ל-client.credits.history() כדי לקבל כל תנועה ביתרה, ול-exportHistory() כדי לקבל את אותה רשימה כקובץ CSV.
האם להתקנות באירוח עצמי יש מחירים בקרדיטים?
לא. בהתקנות באירוח עצמי של מהדורת Community ושל מהדורת Business אין מערכת קרדיטים, ולכן המחירים של המודלים ועלויות הקרדיטים לא מופיעים בתשובות שלהן.
דפים קשורים
הרצת רכיבים
קרדיטים
בחירת מודל
מודלי AI ב-Nodaro
קרדיטים
עודכן לאחרונה