דלג לתוכן
בחזרה לNymbot

בסיס ידע מפתחים

רזולוציה, top-ups ו keys

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

בדוק את האיזון

שניהם משאבים שלך, וכמה של כיסוי המפתח הזה משמש.

GET https://nymbot.ai/api/v1/credits/balance אתה צריך מפתח API. POST זה עובד גם עבור לקוחות שמחכים לזה.

balance הוא שני משקלים יחד בדולרים במחיר Bitcoin הנוכחי, עבור כלים שמצפים מספר יחיד (null אם המחיר לא ניתן לקרוא).השאר הוא בכרטיסי אשראי ופרטי, וזה איך המשאבים למעשה נשמרים. key מפתח שהגיע לקו שלו עדיין יכול לבדוק את האיזון.

תשובות

{
  "balance": 49.18,
  "balance_sats": 42037,
  "standard": { "credits": 120.4, "sats": 1204 },
  "pro": { "credits": 408.33, "sats": 40833 },
  "key": {
    "id": "4f0c9a1be27d3856",
    "name": "laptop scripts",
    "limit_sats": 20000,
    "period_used_sats": 3412,
    "total_used_sats": 18230,
    "reset_period": "monthly",
    "reset_at": "2026-10-01T00:00:00Z"
  }
}
סטטוסמתי
401המפתח חסר, לא ידוע, בוטל או נגמר.

cURL

curl https://nymbot.ai/api/v1/credits/balance \
  -H "Authorization: Bearer $NYMBOT_API_KEY"

Python

import os
import requests

res = requests.get(
    "https://nymbot.ai/api/v1/credits/balance",
    headers={"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]},
)
balance = res.json()
print(balance["standard"]["sats"], balance["pro"]["sats"])

JavaScript

const res = await fetch("https://nymbot.ai/api/v1/credits/balance", {
  headers: { "Authorization": "Bearer " + process.env.NYMBOT_API_KEY },
});
const balance = await res.json();
console.log(balance.standard.sats, balance.pro.sats);

שיטות תשלום

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

GET https://nymbot.ai/api/v1/topup/payment-methods אין צורך במפתח.

Top-up הוא 10 עד 1,000,000 sats; Pro top-up חייב לקנות לפחות קרדיט Pro אחד, אז זה מתחיל ב 100 sats. bulk_bonus מציג את האשראי הנוסף על Top-ups גדולים יותר, אותו הדבר כמו באפליקציה: 10%, 15% או 20% יותר על Top-ups סטנדרטיים מ 500, 1,000 או 5,000 sats, ועל Pro Top-ups מ 5,000, 10,000 או 50,000 sats.

תשובות

{
  "supported_methods": [
    {
      "method": "btc-lightning",
      "display_name": "Bitcoin Lightning",
      "supported_currencies": ["SATS", "USD", "BTC"],
      "limits": {
        "SATS": { "min": 10, "max": 1000000 },
        "USD": { "min": 0.02, "max": 1170 },
        "BTC": { "min": 1e-7, "max": 0.01 }
      },
      "tiers": ["standard", "pro"],
      "default_tier": "pro",
      "tier_min_sats": { "standard": 10, "pro": 100 },
      "sats_per_credit": { "standard": 10, "pro": 100 },
      "bulk_bonus": [
        { "bonus": 0.1, "standard_sats": 500, "pro_sats": 5000 },
        { "bonus": 0.15, "standard_sats": 1000, "pro_sats": 10000 },
        { "bonus": 0.2, "standard_sats": 5000, "pro_sats": 50000 }
      ]
    }
  ]
}

cURL

curl https://nymbot.ai/api/v1/topup/payment-methods

Python

import requests

methods = requests.get("https://nymbot.ai/api/v1/topup/payment-methods").json()
print(methods["supported_methods"][0]["limits"])

JavaScript

const methods = await (await fetch("https://nymbot.ai/api/v1/topup/payment-methods")).json();
console.log(methods.supported_methods[0].limits);

צפייה ב-Up Over Lightning

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

POST https://nymbot.ai/api/v1/topup/create/btc-lightning אתה צריך מפתח API.

שדהסוגדרושהתיאור
amountמספרכֵּןעד כמה, בתוך currencyמספר שלם למטרה.
currencyStringלאSATS (ההתנצלות היא USD או BTCדולרים מוחלפים במחיר Bitcoin הנוכחי.
tierStringלאpro (הפסקת התשלום) או standardאיזו איזון הלוואה הולכת אליו.

אשראי סטנדרטי הוא 10 sats ו Pro אשראי 100 sats, בתוספת כל בונוס נפח; credits תגידו מה יוסיף החשבון הזה.

תשובות

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "payment_request": "lnbc100u1p5...",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": "2026-09-30T09:27:00Z",
  "status": "pending"
}
סטטוסמתי
400שיטה נוספת בדרך (unsupported_method, מטבע לא ידוע (unsupported_currency(למשל, סכום שנמצא מתחת למינימום או סכום שחסר)amount_too_small(למעלה מ-100 אלף ש"ח)amount_too_large) או נדחתה על ידי הארנק Lightning (amount_out_of_range).
429יותר מ 60 חשבונות עבור נימ הזה, או 120 מכתובת זו, בשעה אחת (rate_limit_exceededעם Retry-After).
502כרגע לא ניתן להגיש חשבונית (invoice_unavailableעם Retry-After).

cURL

curl https://nymbot.ai/api/v1/topup/create/btc-lightning \
  -H "Authorization: Bearer $NYMBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount": 10000, "currency": "SATS", "tier": "pro"}'

Python

import os
import requests

res = requests.post(
    "https://nymbot.ai/api/v1/topup/create/btc-lightning",
    headers={"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]},
    json={"amount": 10000, "currency": "SATS", "tier": "pro"},
)
invoice = res.json()
print(invoice["payment_request"])

JavaScript

const res = await fetch("https://nymbot.ai/api/v1/topup/create/btc-lightning", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + process.env.NYMBOT_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ amount: 10000, currency: "SATS", tier: "pro" }),
});
const invoice = await res.json();
console.log(invoice.payment_request);

בדיקת Top-Up

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

GET https://nymbot.ai/api/v1/topup/status/{invoice_id} - זקוק למפתח מהנימה שביצעה את החשבון.

status זה pending (עדיין לא הוגשה תשלום) paid (שלם, אבל עדיין לא הוענק; בדוק שוב), credited (על חשבון שלך) או expired (לא משלמים בזמן) שדות האיזון הם עבור הרמה שהחשבון עולה עליה.

תשובות

{
  "invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
  "status": "credited",
  "amount_sats": 10000,
  "credits": 115,
  "tier": "pro",
  "expires_at": null,
  "balance_credits": 523.33,
  "balance_sats": 52333
}
סטטוסמתי
400ה-ID אינו ה-ID בעל 64 תווים מהשיחה שנוצרה.
404אין חשבונית על ידי זה id עבור nym שלך (invoice_not_found).

cURL

curl https://nymbot.ai/api/v1/topup/status/$INVOICE_ID \
  -H "Authorization: Bearer $NYMBOT_API_KEY"

Python

import os, time
import requests

headers = {"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]}
url = "https://nymbot.ai/api/v1/topup/status/" + invoice["invoice_id"]

while True:
    status = requests.get(url, headers=headers).json()["status"]
    if status in ("credited", "expired"):
        break
    time.sleep(3)
print(status)

JavaScript

const headers = { "Authorization": "Bearer " + process.env.NYMBOT_API_KEY };
const url = "https://nymbot.ai/api/v1/topup/status/" + invoice.invoice_id;

let status;
do {
  await new Promise((r) => setTimeout(r, 3000));
  status = (await (await fetch(url, { headers })).json()).status;
} while (status !== "credited" && status !== "expired");
console.log(status);

רוצה היסטוריה

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

GET https://nymbot.ai/api/v1/queries/history - צריך מפתח API, אשר רואה את הבקשות שלו, או בקשת חתימה מהנימוס שלך, אשר רואה את כל המפתחות.

שדהסוגדרושהתיאור
pageתגית: Queryלאדפדפן 1, עד 1,000; דף גבוה יותר הוא 400 invalid_value.
page_countתגית: Queryלאשורות לדף, כברירת מחדל 20, מקסימום 100.
start_date
end_date
תגית: QueryלאISO 8601 תאריכים ושעות
modelתגית: Queryלארק מודל זה.
typeתגית: Queryלאchat, responses, messages, image, video, speech, transcription או embedding.
all_keysבואינג (בואינג Query)לאעם מפתח אחד: true כולל כל מפתח של אותו nym.Default false.
key_idתגית: Queryלאעם בקשה מסודרת או עם all_keys=trueרק המפתח הזה.

תשובות

{
  "data": [
    {
      "id": "q_71c4e9a0",
      "timestamp": "2026-09-30T08:12:00Z",
      "model": "anthropic/claude-sonnet-5",
      "type": "chat",
      "input_tokens": 1240,
      "output_tokens": 380,
      "cached_tokens": 0,
      "cost_sats": 16.2,
      "cost_usd": 0.01895,
      "balance": "pro",
      "key_id": "4f0c9a1be27d3856",
      "web_search": false,
      "status": "ok"
    }
  ],
  "pagination": { "page": 1, "page_count": 20, "total": 311, "total_pages": 16 }
}

cURL

curl "https://nymbot.ai/api/v1/queries/history?page_count=50&type=chat" \
  -H "Authorization: Bearer $NYMBOT_API_KEY"

Python

import os
import requests

res = requests.get(
    "https://nymbot.ai/api/v1/queries/history",
    headers={"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]},
    params={"page_count": 50, "type": "chat"},
)
for row in res.json()["data"]:
    print(row["timestamp"], row["model"], row["cost_sats"])

JavaScript

const res = await fetch("https://nymbot.ai/api/v1/queries/history?page_count=50&type=chat", {
  headers: { "Authorization": "Bearer " + process.env.NYMBOT_API_KEY },
});
for (const row of (await res.json()).data) console.log(row.timestamp, row.model, row.cost_sats);

חתימת בקשות חשבונות

יצירת, שינוי וביטול מפתחות, סיכום החשבון ואת top-ups אוטומטיים לא לוקחים מפתח API.

האפליקציה עושה את זה בשבילך: הכל בתוכו אש אתה רק צריך את החלק הזה כדי לנהל את המפתחות מהקוד שלך.

החתימה היא אירוע Nostr מסוג 27235 (NIP-98), שנשלח על-ידי Base64 Authorization Header עם המילה Nostr על החזית :

האירוע

{
  "kind": 27235,
  "created_at": 1790726400,
  "tags": [
    ["u", "https://nymbot.ai/api/v1/keys"],
    ["method", "POST"],
    ["nonce", "9c4e21f07a3b...16 random bytes in hex"],
    ["payload", "3f1a0d7c8e2b...sha256 of the exact request body in hex"]
  ],
  "content": "",
  "pubkey": "your public key in hex",
  "id": "...",
  "sig": "..."
}
  • u הוא ה-URL המלא של הבקשה, כולל שורת השאילתה, בדיוק כפי שנשלחה.
  • method זהו שיטת HTTP.
  • payload הוא SHA-256 של הגוף של בקשת גלם, בהקצאה. POST ו PATCH, ואת הגוף שאתה שולח חייב להיות בייט עבור בייט אחד שאתה hashed.
  • created_at זה חייב להיות בתוך 60 שניות מהשעון של השרת.
  • כל אירוע עובד פעם אחת, a GET לא ניתן לשחק מחדש את הכותרת שנלכדה.חתום על כותרת חדשה עבור כל בקשה. nonce תווית עם ערך אקראי כך ששתי בקשות שנחתמו באותה שניה עדיין שונות.
  • הגוף של בקשה חתומה יכול להיות עד 64 KB, והגוף צריך Content-Type: application/json.

אירוע אבוד חוזר 401 missing_nostr_authאחד שנוצר רע, חתום רע, ישן מדי, או עבור כתובת URL שונה, שיטה או גוף חוזרים invalid_nostr_auth, עם הסיבה בהודעה; שימוש חוזר אחד חוזר nostr_auth_replayedהחתימה נבדקת לפני שקראת את הגוף, וכל כתובת יכולה להיכשל בזה 30 פעמים לדקה (כתובת IPv6 נחשבת לכל /64); לאחר מכן היא מקבלת 429 עם Retry-After.

דפדפנים יכולים להתקשר לנקודות הקצה הללו רק מהאתרים של Nymbot (https://nymbot.ai, https://nymchat.app דף בכל אתר אחר לא מקבל כותרות CORS בחזרה, כך שהוא לא יכול לקרוא את מה שהם חוזרים. Originהם לא מושפעים.

המפתח הסודי שלך

חתימה צריכה את המפתח הסודי של נים שלך (The nsecרק לשים את זה בסקריפט על מכונה שאתה סומך עליה, לקרוא אותו מהסביבה במקום לכתוב אותו לקובץ, ולהעדיף את האפליקציה כאשר אתה יכול.

עוזרים אלה בונים את הכותרת. הדוגמאות המאוחרות בדף זה משתמשות בהם. NOSTR_SECRET_HEXcURL one משתמש ב נוק כלי שורת הפקודה, אשר לוקח מפתח nsec או hex, ו sha256sum על ידי macOS, shasum -a 256).

cURL

nostr_auth() {
  method="$1"; url="$2"; body="$3"
  nonce=$(openssl rand -hex 16)
  if [ -n "$body" ]; then
    hash=$(printf '%s' "$body" | sha256sum | cut -d' ' -f1)
    event=$(nak event --sec "$NOSTR_SECRET_HEX" -k 27235 -t "u=$url" -t "method=$method" -t "nonce=$nonce" -t "payload=$hash")
  else
    event=$(nak event --sec "$NOSTR_SECRET_HEX" -k 27235 -t "u=$url" -t "method=$method" -t "nonce=$nonce")
  fi
  printf 'Nostr %s' "$(printf '%s' "$event" | base64 | tr -d '\n')"
}

Python

# pip install coincurve requests
import base64, hashlib, json, os, time
from coincurve import PrivateKey, PublicKeyXOnly

SECRET = bytes.fromhex(os.environ["NOSTR_SECRET_HEX"])

def nostr_auth(method, url, body=b""):
    pubkey = PublicKeyXOnly.from_secret(SECRET).format().hex()
    tags = [["u", url], ["method", method], ["nonce", os.urandom(16).hex()]]
    if body:
        tags.append(["payload", hashlib.sha256(body).hexdigest()])
    created_at = int(time.time())
    serialized = json.dumps([0, pubkey, created_at, 27235, tags, ""], separators=(",", ":"), ensure_ascii=False)
    event_id = hashlib.sha256(serialized.encode()).digest()
    event = {
        "id": event_id.hex(),
        "pubkey": pubkey,
        "created_at": created_at,
        "kind": 27235,
        "tags": tags,
        "content": "",
        "sig": PrivateKey(SECRET).sign_schnorr(event_id).hex(),
    }
    return "Nostr " + base64.b64encode(json.dumps(event).encode()).decode()

JavaScript

// npm install nostr-tools
import { createHash, randomBytes } from "node:crypto";
import { finalizeEvent } from "nostr-tools/pure";

const secret = Buffer.from(process.env.NOSTR_SECRET_HEX, "hex");

export function nostrAuth(method, url, body = "") {
  const tags = [["u", url], ["method", method], ["nonce", randomBytes(16).toString("hex")]];
  if (body) tags.push(["payload", createHash("sha256").update(body).digest("hex")]);
  const event = finalizeEvent(
    { kind: 27235, created_at: Math.floor(Date.now() / 1000), tags, content: "" },
    secret,
  );
  return "Nostr " + Buffer.from(JSON.stringify(event)).toString("base64");
}

חשבונית סיכום

מה מדף ה-API של האפליקציה מראה בחלק העליון: המפתח הציבורי שלך, שניהם שווים, כמה מפתחות פעילים (לא בוטלו או נעלמו), ואת Top-up אוטומטי הגדרות או null כאשר השרת אינו מציע אותם.

GET https://nymbot.ai/api/v1/account צריך A בקשת חתימה.

תשובות

{
  "data": {
    "pubkey": "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
    "balances": {
      "standard": { "credits": 120.4, "sats": 1204 },
      "pro": { "credits": 408.33, "sats": 40833 }
    },
    "keys_active": 3,
    "nwc_auto_topup": {
      "connected": true, "threshold_sats": 5000, "topup_sats": 20000, "tier": "pro",
      "last_topup_at": null, "last_topup_sats": null, "last_error": null
    }
  }
}

cURL

URL=https://nymbot.ai/api/v1/account
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"

Python

import requests

url = "https://nymbot.ai/api/v1/account"
print(requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json())

JavaScript

const url = "https://nymbot.ai/api/v1/account";
const res = await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } });
console.log(await res.json());

ניהול מפתחות

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

אובייקט מפתח

{
  "id": "4f0c9a1be27d3856",
  "name": "laptop scripts",
  "hint": "sk-nymbot-Qm7x…c2Lw",
  "limit_sats": 20000,
  "reset_period": "monthly",
  "reset_at": "2026-10-01T00:00:00Z",
  "expire_at": null,
  "period_used_sats": 3412,
  "total_used_sats": 18230,
  "created_at": "2026-08-14T09:21:07Z",
  "updated_at": "2026-09-02T17:40:55Z",
  "last_used_at": "2026-09-30T08:12:00Z",
  "revoked_at": null
}

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

רשימת מפתחות

GET https://nymbot.ai/api/v1/keys חתם על

שדהסוגדרושהתיאור
include_revokedבואינג (בואינג Query)לאכולל מפתחות מבוטלים.Default false.

תשובות

{ "data": [ { "id": "4f0c9a1be27d3856", "name": "laptop scripts", "hint": "sk-nymbot-Qm7x…c2Lw", "...": "..." } ] }

cURL

URL=https://nymbot.ai/api/v1/keys
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"

Python

import requests

url = "https://nymbot.ai/api/v1/keys"
for key in requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json()["data"]:
    print(key["id"], key["name"], key["period_used_sats"], key["limit_sats"])

JavaScript

const url = "https://nymbot.ai/api/v1/keys";
const { data } = await (await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } })).json();
for (const key of data) console.log(key.id, key.name, key.period_used_sats, key.limit_sats);

להכין מפתח

POST https://nymbot.ai/api/v1/keys חותמים - חוזרים 201.

שדהסוגדרושהתיאור
nameStringכֵּן1 עד 40 תווים, שונים מפתחות הפעילות האחרות שלך (עלול להתעלם מקרה).
limit_satsאינטגרלאמחירי המזומנים במזומן, לפחות 1.השאיר את זה בחוץ ללא מחירי.
reset_periodStringלאdaily, weekly או monthlyדרושים limit_satsהשאירו את זה בחוץ עבור כובע שמעולם לא מחזיר.
expire_atString או integerלאכאשר המפתח מפסיק לעבוד: זמן ISO 8601, או מילישניות מאז 1970.

תשובות (201)

{
  "data": {
    "id": "4f0c9a1be27d3856",
    "name": "laptop scripts",
    "hint": "sk-nymbot-Qm7x…c2Lw",
    "limit_sats": 20000,
    "reset_period": "monthly",
    "key": "sk-nymbot-Qm7x...c2Lw",
    "...": "the rest of the key object"
  }
}
סטטוסמתי
400שם חסר או ארוך מדי; שם כבר בשימוש (duplicate_name(למשל, לא ניתן להשיג את כל המספרים המלאים (למשל, לא ניתן להשיג את כל המספרים המלאים של המספרים המלאים של המספרים המלאים של המספרים המלאים של המספרים המלאים של המספרים המלאים של המספרים המלאים של המספרים המלאים של המספרים המלאים של המספרים המלאים).unknown_parameter); או 25 מפתחות פעיל כבר (too_many_keys).
429יותר מ 60 מפתחות שנוצרו על ידי ניום זה, או 120 מכתובת זו, בשעה אחת (rate_limit_exceededעם Retry-After).

cURL

URL=https://nymbot.ai/api/v1/keys
BODY='{"name":"laptop scripts","limit_sats":20000,"reset_period":"monthly"}'
curl "$URL" \
  -H "Authorization: $(nostr_auth POST "$URL" "$BODY")" \
  -H "Content-Type: application/json" \
  -d "$BODY"

Python

import json
import requests

url = "https://nymbot.ai/api/v1/keys"
body = json.dumps({"name": "laptop scripts", "limit_sats": 20000, "reset_period": "monthly"}).encode()
res = requests.post(
    url,
    data=body,
    headers={"Authorization": nostr_auth("POST", url, body), "Content-Type": "application/json"},
)
print(res.json()["data"]["key"])

JavaScript

const url = "https://nymbot.ai/api/v1/keys";
const body = JSON.stringify({ name: "laptop scripts", limit_sats: 20000, reset_period: "monthly" });
const res = await fetch(url, {
  method: "POST",
  headers: { "Authorization": nostrAuth("POST", url, body), "Content-Type": "application/json" },
  body,
});
console.log((await res.json()).data.key);

קריאת מפתח אחד

GET https://nymbot.ai/api/v1/keys/{id} חתם על

חזרה {"data": {…}} עם האובייקט המפתח, או 404 key_not_found אם אין מפתח שלך יש מזהה זה.

cURL

URL=https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"

Python

import requests

url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856"
print(requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json()["data"])

JavaScript

const url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856";
console.log((await (await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } })).json()).data);

שינוי מפתח

PATCH https://nymbot.ai/api/v1/keys/{id} חתם על

שלח כל אחד name, limit_sats, reset_period ו expire_atעם אותם כללים כמו בעת ביצוע מפתח. null שחרור שדה: אין כיסוי, אין הגדרת מחדש, אין תוקף. שינוי תקופת הגדרת מחדש מתחיל תקופה חדשה מאפס.400 key_revoked) החזרה {"data": {…}} עם האובייקט המפתח המעודכן.

cURL

URL=https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856
BODY='{"limit_sats":50000,"expire_at":null}'
curl -X PATCH "$URL" \
  -H "Authorization: $(nostr_auth PATCH "$URL" "$BODY")" \
  -H "Content-Type: application/json" \
  -d "$BODY"

Python

import json
import requests

url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856"
body = json.dumps({"limit_sats": 50000, "expire_at": None}).encode()
res = requests.patch(
    url,
    data=body,
    headers={"Authorization": nostr_auth("PATCH", url, body), "Content-Type": "application/json"},
)
print(res.json()["data"])

JavaScript

const url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856";
const body = JSON.stringify({ limit_sats: 50000, expire_at: null });
const res = await fetch(url, {
  method: "PATCH",
  headers: { "Authorization": nostrAuth("PATCH", url, body), "Content-Type": "application/json" },
  body,
});
console.log((await res.json()).data);

ביטול מפתח

DELETE https://nymbot.ai/api/v1/keys/{id} חתם על

עוצר את המפתח בבת אחת, טוב.הוא נשאר ברשימה עם revoked_at מופיע, ניתן לראות עם include_revoked=trueביטול מפתח שכבר בוטל עונה באותו אופן: רק 50 המפתחות החדשות ביותר שנמחקו נשמרות; אלה הישנים נמחקים כאשר מפתח אחר בוטל.

תשובות

{ "data": { "id": "4f0c9a1be27d3856", "revoked": true } }

cURL

URL=https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856
curl -X DELETE "$URL" -H "Authorization: $(nostr_auth DELETE "$URL")"

Python

import requests

url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856"
print(requests.delete(url, headers={"Authorization": nostr_auth("DELETE", url)}).json())

JavaScript

const url = "https://nymbot.ai/api/v1/keys/4f0c9a1be27d3856";
const res = await fetch(url, { method: "DELETE", headers: { "Authorization": nostrAuth("DELETE", url) } });
console.log(await res.json());

תגית: NWC Auto-top-up

חיבור ארנק Lightning עם Nostr Wallet Connect ו- Nymbot מעלה את האיזון בעצמם כאשר הוצאות API פועלות אותו נמוך. בקשת חתימה.

איך זה עובד: לאחר בקשת API מוטלת על הסכום שבחרת לצפות, אם הסכום הזה ירד מתחת לסף שלך, Nymbot עושה חשבונית עבור הסכום העליון שלך, מבקש את הארנק שלך לשלם את זה, ומוסיף את ההלוואה. זה עולה למעלה פעם אחת בכל 5 דקות עבור כל נים ומשקל, כך שבץ של בקשות לא יכול לשטוף את הארנק. הוצאות באפליקציות לא להפעיל את זה. הזמן והגודל של העליון האחרון, ואת השגיאה האחרונה, נמצאים בהגדרות; אם תשלום עבר לאחר שגיאה, בדוק את החשבונית שלה עם מצב Top-Up אשראי את זה.

לפני שאתה מחבר ארנק

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

חיבור ארנק

POST https://nymbot.ai/api/v1/nwc-auto-topup/connect חתם על

שדהסוגדרושהתיאור
nwc_urlStringכֵּןהקשר המשותף, מתחיל nostr+walletconnect://Nymbot מבקש את הארנק עבור get_info לפני שאתה שומר אותו, ולאחסן אותו מוצפן.
threshold_satsאינטגרכֵּןמעלה את זה כאשר האיזון נופל מתחת לזה הרבה sats.
topup_satsאינטגרכֵּןכמה להוסיף בכל פעם. 1,000 עד 1,000,000 sats.
tierStringלאpro (הפסקת התשלום) או standard: את האיזון לצפות ולמעלה.

תשובות

{
  "data": {
    "connected": true,
    "threshold_sats": 5000,
    "topup_sats": 20000,
    "tier": "pro",
    "last_topup_at": null,
    "last_topup_sats": null,
    "last_error": null
  }
}
סטטוסמתי
400לא קישור לקטגוריה (invalid_nwc_url(החוברת לא ענתה על השידור שלה)nwc_unreachable) או סירב לבדוק (nwc_rejected); החיבור אינו יכול לשלם חשבונות (nwc_missing_permission); או סכום מחוץ לגבולות.
501לא ניתן להפעיל את המכשיר באופן אוטומטי (nwc_unavailableכך גם לגבי שתי נקודות הסוף האחרות.

cURL

URL=https://nymbot.ai/api/v1/nwc-auto-topup/connect
BODY='{"nwc_url":"nostr+walletconnect://...","threshold_sats":5000,"topup_sats":20000,"tier":"pro"}'
curl "$URL" \
  -H "Authorization: $(nostr_auth POST "$URL" "$BODY")" \
  -H "Content-Type: application/json" \
  -d "$BODY"

Python

import json, os
import requests

url = "https://nymbot.ai/api/v1/nwc-auto-topup/connect"
body = json.dumps({
    "nwc_url": os.environ["NWC_URL"],
    "threshold_sats": 5000,
    "topup_sats": 20000,
    "tier": "pro",
}).encode()
res = requests.post(
    url,
    data=body,
    headers={"Authorization": nostr_auth("POST", url, body), "Content-Type": "application/json"},
)
print(res.json())

JavaScript

const url = "https://nymbot.ai/api/v1/nwc-auto-topup/connect";
const body = JSON.stringify({
  nwc_url: process.env.NWC_URL,
  threshold_sats: 5000,
  topup_sats: 20000,
  tier: "pro",
});
const res = await fetch(url, {
  method: "POST",
  headers: { "Authorization": nostrAuth("POST", url, body), "Content-Type": "application/json" },
  body,
});
console.log(await res.json());

לקרוא את ההגדרות

GET https://nymbot.ai/api/v1/nwc-auto-topup חתם על

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

cURL

URL=https://nymbot.ai/api/v1/nwc-auto-topup
curl "$URL" -H "Authorization: $(nostr_auth GET "$URL")"

Python

import requests

url = "https://nymbot.ai/api/v1/nwc-auto-topup"
print(requests.get(url, headers={"Authorization": nostr_auth("GET", url)}).json())

JavaScript

const url = "https://nymbot.ai/api/v1/nwc-auto-topup";
console.log(await (await fetch(url, { headers: { "Authorization": nostrAuth("GET", url) } })).json());

מחסום

DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection חתם על

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

תשובות

{ "data": { "connected": false, "threshold_sats": null, "topup_sats": null, "tier": null, "last_topup_at": null, "last_topup_sats": null, "last_error": null } }

cURL

URL=https://nymbot.ai/api/v1/nwc-auto-topup/connection
curl -X DELETE "$URL" -H "Authorization: $(nostr_auth DELETE "$URL")"

Python

import requests

url = "https://nymbot.ai/api/v1/nwc-auto-topup/connection"
print(requests.delete(url, headers={"Authorization": nostr_auth("DELETE", url)}).json())

JavaScript

const url = "https://nymbot.ai/api/v1/nwc-auto-topup/connection";
const res = await fetch(url, { method: "DELETE", headers: { "Authorization": nostrAuth("DELETE", url) } });
console.log(await res.json());

תשלום לפי בקשה ללא מפתח

נקודות הקצה במחיר קבוע ניתן לשלם על בקשה אחת בכל פעם על ידי Lightning, ללא מפתח, ללא חשבון ואין איזון: POST /images/generations, POST /images/edits, POST /videos, POST /audio/speech, POST /audio/transcriptions, POST /audio/translations ו POST /embeddingsהצ'אט, התשובות והודעות תמיד זקוקות למפתח; בקשה שמחזיקה במפתח מחויבת לאיזון כרגיל; זרימת התשלום מתחילה רק כאשר אין מפתח שנשלח.

Nymbot מדבר על שתי גרסאות של אותו רעיון, מאותו backend: Lightning Labs' א 402 (גם תחת השם הישן שלו, LSAT) ופרויקט IETF תשלום תוכנית אימות HTTP עם lightning שיטה ו charge השתמש במה שהלקוח שלך מבין.

להפעיל את השרת שלך

תשלום ללא מפתח הוא רק כאשר API_L402_SECRET מחזיק לפחות 32 bytes אקראיים, כגון hex (64 תווים) או base64 (44). openssl rand -hex 32ערך קצר יותר או אפשרי לנחש מפעיל את התכונה ומזכיר מדוע. API_L402_SECRET_PREVIOUS במשך יום אחד: אישורים, כתובות URL של מצב ואתגרים שנעשו תחת זה ממשיכים לעבוד עד שהם נופלים.

האתגר

שלח את הבקשה עם לא Authorization אם זה נכון, שום דבר לא פועל, ואתה מקבל 402 Payment Required עם חשבונית עבור בדיוק מה שביקוש זה עולה: אותו מחיר מפתח היה משלם, המוחלף ב 10 sats קרדיט סטנדרטי או 100 sats קרדיט פרו ומסובב עד sat שלם (לפחות 1 sat, ולפחות 0.05 מינימום אשראי). WWW-Authenticate אתגרים עבור אותה חשבונית:

HTTP/1.1 402 Payment Required
Content-Type: application/problem+json; charset=utf-8
Cache-Control: no-store
WWW-Authenticate: L402 macaroon="AgJC...", invoice="lnbc2370n1..."
WWW-Authenticate: LSAT macaroon="AgJC...", invoice="lnbc2370n1..."
WWW-Authenticate: Payment id="kM9x...", realm="nymbot", method="lightning", intent="charge",
    request="eyJhbW91bnQiOiIyMzciLC...", description="Nymbot API POST /images/generations (237 sats)",
    digest="sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:", expires="2026-09-30T12:15:00.000Z",
    opaque="eyJlbmRwb2ludCI6IlBPU1QgL2ltYWdlcy9nZW5lcmF0aW9ucyJ9"

{
  "type": "https://paymentauth.org/problems/payment-required",
  "title": "Payment Required",
  "status": 402,
  "detail": "This request costs 237 sats. Pay the Lightning invoice, then send the identical request again ...",
  "challengeId": "kM9x...",
  "amount_sats": 237,
  "invoice": "lnbc2370n1...",
  "payment_hash": "9db1370f...",
  "expires_at": "2026-09-30T12:15:00.000Z",
  "error": { "message": "This request costs 237 sats. ...", "type": "payment_required", "code": "payment_required", "param": null }
}

התשלום request עקבו אחרי base64url JSON base64url JSON {"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.

האתגר הוא קשור לנקודה הסופית, ל Content-Type (הסוג של המדיה, ובמקרה של חלקים מרובים, הגבול שלה) ול- SHA-256 של הבייטים המדויקים של הגוף שאתה שולח, והוא נמשך 15 דקות. זהות בקשה נוספת: אותו דבר Content-Type תגיות קשורות תגיות קשורות תגיות קשורות תגיות קשורות תגיות קשורות תגיות קשורות תגיות קשורות תגיות קשורות תגיות קשורות תגיות קשורות תגיות/images/edits, /audio/transcriptions, /audio/translationsרוב ספריות HTTP בוחרות גבול חדש בכל פעם שהם מקודדים טופס, אז לקודד אותו פעם אחת ולשלוח את הבייטים האלה פעמיים.

כל כתובת יכולה לבקש 30 אתגרים לדקה (כתובת IPv6 מחושבת כ /64 שלמה). בקשות שהכתובת שלהם לא ידועה חולקות 10 דקה יותר קפדנית, ויש מגבלת כללית על אתגרים Nymbot בעיות בכל הכתובות; בקשה נדחתה לפני שנעשה אתגר (לדוגמה, עם גוף שאינו JSON תקף) לא נחשב כלפי זה. 429 עם Retry-Afterנקודות קצה בתשלום שהתקבלו ללא מפתח או הכרזה נחשבות גם למגבלת הכללית של 120 בקשות לא מאושרות לדקה לכל כתובת. Content-Type זה לא application/json (או multipart/form-data על פי ההסכם, הוא מסרב 415 אף פעם לא מקבלים חשבונית.

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

לשלוח את התשלום

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

התכניתHeader
א 402Authorization: L402 <macaroon>:<preimage> (LSAT גם זה עובד)
תשלוםAuthorization: Payment <base64url JSON>היכן נמצא JSON {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}}

בקשה בתשלום עונה בדיוק כמו זו שנעשתה עם מפתח, למעט nymbot לאובייקט אין שדות איזון: {"payment": "l402", "tier": "pro", "paid_sats": 237, "charged_sats": 237}וכאן אין X-Nymbot-Balance-Sats בקשה ששולמה עם תוכנית התשלום מקבלת גם Payment-Receipt כותרת (base64url JSON with the challenge id, the payment hash as reference, status ו timestampבקשות בתשלום אינן קשורות לכל נים, ולכן הן לא מופיעות בהיסטוריה של השאילתה.

סטטוסמתי
402 payment_already_usedכל תשלום משלם עבור בקשה אחת.התשובה היא אתגר חדש עבור בקשה זו, כך לקוח שמאחסן את הסמכות האחרונה שלו (כגון lnget א) פשוט לחזור על זה.
402 payment_mismatchההרשמה נמסרה לנקודה נוספת, Content-Type או גוף, או לשלם פחות מאשר בקשה זו עכשיו עולה. אתגר חדש עבור בקשה זו מגיע עם זה; אם התשלום היה קטן מדי, מה שילמתם חוזר כאתגר. חזר טוקיו (refund_token ו refund_sats בתוך הגוף )
402 payment_expiredיותר מ-15 דקות חלפו מאז האתגר.אתגר חדש מגיע איתו.אם התמונה הקדמית מראה שאתה שילמת, מה ששילמת חוזר כאתגר. חזר טוקיו (refund_token ו refund_sats לאחר מכן, לאחר מכן, המשתמש משתמש.
401 invalid_preimageהתמונה המוקדמת אינה חותמת את חותמת התשלום של החשבונית.
401 invalid_payment_credentialהכרזה שגויה, השתנתה לאחר ש-Nymbot הוציאה אותה, או שמות שקיות תשלום ש-Nymbot מעולם לא הוציאה חשבונית.
429 rate_limit_exceededיותר מ-30 אישורים או מפתחות שלא הצליחו לאמת הגיעו מהכתובת הזו בתוך דקה, או טוקן החזר אחד נשלח יותר מ 60 פעמים בדקה. Retry-After.

cURL

BODY='{"model":"nano-banana","prompt":"a lighthouse at dusk","response_format":"b64_json"}'
URL=https://nymbot.ai/api/v1/images/generations

# 1. Get the challenge
CH=$(curl -s -D - -o /dev/null "$URL" -H "Content-Type: application/json" -d "$BODY" | grep -i '^www-authenticate: L402')
MAC=$(echo "$CH" | sed -E 's/.*macaroon="([^"]+)".*/\1/')
INVOICE=$(echo "$CH" | sed -E 's/.*invoice="([^"]+)".*/\1/')

# 2. Pay $INVOICE with your wallet and copy the preimage
PREIMAGE=...

# 3. Send the identical request with the credential
curl "$URL" -H "Content-Type: application/json" -H "Authorization: L402 $MAC:$PREIMAGE" -d "$BODY"

lnget

# lnget (Lightning Labs) pays L402 challenges from your own lnd node and retries for you
lnget -X POST -H "Content-Type: application/json" \
  -d '{"model":"nano-banana","prompt":"a lighthouse at dusk","response_format":"b64_json"}' \
  https://nymbot.ai/api/v1/images/generations

Python

import base64, json, re
import requests

url = "https://nymbot.ai/api/v1/images/generations"
body = json.dumps({"model": "nano-banana", "prompt": "a lighthouse at dusk", "response_format": "b64_json"}).encode()
headers = {"Content-Type": "application/json"}

challenge = requests.post(url, data=body, headers=headers)
assert challenge.status_code == 402
info = challenge.json()
print("Pay", info["amount_sats"], "sats:", info["invoice"])

preimage = pay_with_your_wallet(info["invoice"])  # 64 hex characters

# L402
mac = re.search(r'L402 macaroon="([^"]+)"', challenge.headers["WWW-Authenticate"]).group(1)
res = requests.post(url, data=body, headers={**headers, "Authorization": f"L402 {mac}:{preimage}"})
print(res.json()["nymbot"])

JavaScript

const url = "https://nymbot.ai/api/v1/images/generations";
const body = JSON.stringify({ model: "nano-banana", prompt: "a lighthouse at dusk", response_format: "b64_json" });
const headers = { "Content-Type": "application/json" };

const challenge = await fetch(url, { method: "POST", headers, body });
const www = challenge.headers.get("www-authenticate");

// The Payment scheme: echo every challenge parameter back with the preimage
const start = www.indexOf("Payment ");
const params = Object.fromEntries([...www.slice(start + 8).matchAll(/(\w+)="((?:[^"\\]|\\.)*)"/g)].map((m) => [m[1], m[2]]));
const { invoice } = JSON.parse(Buffer.from(params.request, "base64url").toString()).methodDetails;
const preimage = await payWithYourWallet(invoice);

const credential = Buffer.from(JSON.stringify({ challenge: params, payload: { preimage } })).toString("base64url");
const res = await fetch(url, { method: "POST", headers: { ...headers, Authorization: `Payment ${credential}` }, body });
console.log((await res.json()).nymbot, res.headers.get("payment-receipt"));

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

וידאו

תשלום POST /videos תשובות 202 כמו מפתח אחד, פלוס a status_url: GET זה נחתם ועובד במשך 24 שעות, כל עוד העבודה נשמרת.

{
  "id": "vid_...",
  "status": "in_progress",
  "status_url": "https://nymbot.ai/api/v1/videos/vid_...?exp=1790000000&sig=...",
  "nymbot": {
    "payment": "l402", "tier": "pro", "paid_sats": 4800, "charged_sats": 4800,
    "refund_token": "REFUND-5E0B..."
  }
}

שמור את refund_token התשובה היא פשוטה: זה לא מופיע בסרטון, זה לא מופיע (GET /api/v1/l402/refunds תשובות "status": "pending"); אם ההפצה נכשלה ללא חיוב, התשלום נחת על זה. refund_sats עבור עבודה משולמת, אך לעולם לא את ה- token, כך שיתוף ה- URL של המצב אינו משתף את ההחזר.

החזר

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

{
  "error": {
    "message": "The image generator failed. Nothing was charged. Please try again. The 237 sats you paid are on refund token REFUND-...",
    "type": "api_error",
    "code": "upstream_error",
    "refund_token": "REFUND-0C15DBED145D59131BA70298A413ADEB3D9B9AB082C476EA70A5BD38FCA5DE6D",
    "refund_sats": 237,
    "refund_expires_at": "2026-10-30T12:00:00.000Z"
  }
}

החלקים הלא משתמשים חוזרים באותו אופן: אם ביקשתם שתי תמונות ואחת לא הוגשה, התשובה הצליחה. nymbot אובייקט נושאת חותם החזר עבור החסר; עותק שהאורך שלו לא יכול להיקרא מראש הוא מוערך עבור הארוך ביותר הקובץ יכול להיות (לעולם לא יותר מ 30 דקות), ואת ההבדל לאורך האמיתי חוזר כ חותם החזר; אם זה מתברר להיות יותר מ 30 דקות, זה נדחה עם 413 התשלומים מחזירים את מה שההערכה מחזיקה בחזרה.וידאו שנכשל מחזיר את הכרטיס שהצגת.

טוקן החזר כספי הוא קוד אקראי של 256 סיביות. Nymbot מאחסן רק את ההאש שלו, והוא נופל לאחר 30 ימים.

  • לשלם עם זה. שלח Authorization: Bearer REFUND-… על כל אחד מהחומרים המופיעים לעיל (החומרים המופיעים לעיל אינם מופיעים במקומות מסוימים, אלא אם כן הם מופיעים במקומות מסוימים).refund_token_sats ב The nymbot מטען שווה פחות מהתשובות לבקשתו 402 refund_insufficient· כישלון ללא חיוב מטיל את התעריף בחזרה על אותו טוקן.
  • בדוק את זה. GET /api/v1/l402/refunds עם אותו header חוזר {"sats": 237, "status": "open", "expires_at": "..."}.
  • ניתן להשתמש בטוקיו אחד עד 60 פעמים לדקה.
  • העבירו את זה ל-NIM. תכניסו אותו לתוך מחזירים מתנה באפליקציית Nymbot, או להתקשר POST /api/v1/l402/refunds/redeem עם A בקשת חתימה ו {"refund_token": "REFUND-...", "balance": "standard"} (או "pro"כל הכרטיסים הולכים לאיזון (10 sats כל אחד על סטנדרטי, 100 על פרו); sats שאינם עושים אשראי שלם להישאר על התווית עבור בקשות API.

cURL

URL=https://nymbot.ai/api/v1/l402/refunds/redeem
BODY='{"refund_token":"REFUND-...","balance":"standard"}'
curl "$URL" \
  -H "Authorization: $(nostr_auth POST "$URL" "$BODY")" \
  -H "Content-Type: application/json" \
  -d "$BODY"

תשובות

{ "data": { "credited": 23, "tier": "standard", "balance_credits": 123, "remaining_sats": 7 } }