Baza znanja razvijalci
Ravnovesje, top-ups in ključi
Preverite, kaj imate, nadgradite Lightning, nadgradite samodejno iz lastne denarnice, si oglejte, koliko stane vsaka zahteva in upravljajte ključe iz kode.
Ta stran je zaradi priročnosti strojno prevedena. Velja angleški izvirnik.
Preverjanje ravnotežja
Oba vaša ravnotežja in koliko tega ključa je uporabljeno.
GET https://nymbot.ai/api/v1/credits/balance Potrebujete API ključ. POST Deluje tudi za stranke, ki to pričakujejo.
balance je dva ravnovesja skupaj v dolarjih po trenutni ceni Bitcoin, za orodja, ki pričakujejo eno število (null če se cena ne more prebrati). preostanek je v kreditih in zneskih, kar je način, kako se ravnotežje dejansko ohranja. key Ključ, ki je dosegel svojo mejo, lahko še vedno preveri ravnovesje.
Odgovor
{
"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"
}
}
| statusa | Kdaj |
|---|---|
401 | Ključ je manjkajoč, neznan, preklican ali potekel. |
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);
Načini plačila
Kako lahko nadgradite, in meje. Lightning je edina metoda.
GET https://nymbot.ai/api/v1/topup/payment-methods Ključ ni potreben.
Top-up je 10 do 1.000.000 sats; Pro top-up mora kupiti vsaj en Pro kredit, zato se začne pri 100 sats. bulk_bonus navaja dodaten kredit na večjih top-upih, enako kot v aplikaciji: 10%, 15% ali 20% več na standardnih top-upih od 500, 1.000 ali 5.000 sats, in na Pro top-upih od 5.000, 10.000 ali 50.000 sats.
Odgovor
{
"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);
Spuščanje nad Lightning
Ustvarja Račun Lightning, ki dodaja kredit k nimmu, ki mu pripada ključ. Plačajte ga iz katere koli denarnice Lightning, nato Preverite ga Za dodajanje kredita.
POST https://nymbot.ai/api/v1/topup/create/btc-lightning Potrebujete API ključ.
| polje | Vrsta | Potrebno | Opis |
|---|---|---|---|
amount | število | ja | Koliko je, v currencyCelotno število za stavo. |
currency | String | ne | SATS (v primeru nepravilnosti) USD ali BTCDolarji se pretvorijo po trenutni ceni Bitcoin. |
tier | String | ne | pro (odvisno od dolžnosti) ali standard: v katero bilanco gre kredit. |
Standardni kredit je 10 sats in Pro kredit 100 sats, plus kateri koli bonus v razsutem stanju;
credits Povejte, kaj bo dodal ta članek.
Odgovor
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"payment_request": "lnbc100u1p5...",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": "2026-09-30T09:27:00Z",
"status": "pending"
}
| statusa | Kdaj |
|---|---|
400 | Druga metoda na poti (unsupported_method), neznana valuta (unsupported_currency) ali ravni, manjkajoči znesek ali znesek pod najmanjšo vrednostjo (amount_too_small(več kot 1 milijon dolarjev)amount_too_large) ali zavrnjen s svetlobno denarnico (amount_out_of_range). |
429 | Več kot 60 računov za to nimm, ali 120 iz tega naslova, v eni uri (rate_limit_exceeded, z Retry-After). |
502 | Trenutno ni mogoče izvesti nobenega računa (invoice_unavailable, z 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);
Preverjanje top-up
Vpraša, ali je bil račun plačan in, ko je, dodaja kredit. Preverjanje je tisto, kar ga kreditira, zato po plačilu preverite, dokler stanje ni creditedPonovno preverjanje pozneje je varno: kredit pristane enkrat, ne glede na to, kolikokrat vprašate.
GET https://nymbot.ai/api/v1/topup/status/{invoice_id} - potrebuje ključ od nimma, ki je naredil račun.
status je pending (za zdaj še ni plačana) paid (plačano, vendar še ni kreditirano; preverite še enkrat), credited (na vašem ravnovesju) ali expired (ni plačano pravočasno). polja ravnovesja so za raven, na kateri se obračuna račun.
Odgovor
{
"invoice_id": "b7d41e0c95a2f38e6c1d0e9a4b7f2c61d3e8a05f9b2c4d7e1a6f3b8c0d5e2a9f4",
"status": "credited",
"amount_sats": 10000,
"credits": 115,
"tier": "pro",
"expires_at": null,
"balance_credits": 523.33,
"balance_sats": 52333
}
| statusa | Kdaj |
|---|---|
400 | ID ni 64-mestni ID iz klica za ustvarjanje. |
404 | Nihče ne ve, kje se nahaja tvoja hiša (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);
Želi zgodovino
Ena vrstica na zahtevo: kaj je bilo, kateri model, koliko žetonov in koliko stane. Ni opozoril ali odgovorov, zato noben ni vrnjen. Vrstice so shranjene 90 dni, najprej najnovejše. Ključ, ki je dosegel svojo mejo, lahko še vedno prebere svojo zgodovino.
GET https://nymbot.ai/api/v1/queries/history — potrebuje API ključ, ki vidi lastne zahteve, ali Podpisana zahteva iz vašega nimma, ki vidi vsak ključ.
| polje | Vrsta | Potrebno | Opis |
|---|---|---|---|
page | Povpraševanje (vključno z vprašanjem) | ne | Privzeto 1, največ 1000; višja stran je 400 invalid_value. |
page_count | Povpraševanje (vključno z vprašanjem) | ne | Vrstice na stran. Privzeto 20, največ 100. |
start_dateend_date | String (poizvedba) | ne | ISO 8601 datumi in časi. |
model | String (poizvedba) | ne | Samo ta model. |
type | String (poizvedba) | ne | chat, responses, messages, image, video, speech, transcription ali embedding. |
all_keys | Boolean (poizvedba) | ne | Z enim ključem: true vključuje vsak ključ istega nimma. privzeto false. |
key_id | String (poizvedba) | ne | S podpisano zahtevo ali s all_keys=trueSamo ta ključ. |
Odgovor
{
"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);
Podpis računskih zahtevkov
Ustvarjanje, spreminjanje in preklic ključev, povzetek računa in samodejni top-up ne vzamejo API ključa. Vzamejo podpis iz vašega nimma, tako da lahko ujet ključ porabi do svoje meje, vendar nikoli ne more narediti drugega ključa ali dvigniti lastne meje.
Aplikacija to počne za vas: vse v svoji ogenj Ta odsek potrebujete le za upravljanje ključev iz lastne kode.
Podpis je dogodek Nostr vrste 27235 (NIP-98), ki je bil poslan s kodiranjem base64 v
Authorization Header z besedo Nostr Na sprednji strani:
Dogodek
{
"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": "..."
}
uje celoten URL zahteve, vključen niz poizvedb, točno tako, kot je bil poslan.methodTo je HTTP metoda.payloadje SHA-256 surovega zahtevnega telesa, v hex.POSTinPATCH, in telo, ki ga pošljete, mora biti bajt za bajt, ki ste ga hashed.created_atmora biti v 60 sekundah od ure strežnika.- Vsak dogodek deluje enkrat, a
GETvključena, tako da zajetega glave ni mogoče predvajati. Podpišite novega za vsako zahtevo.nonceoznačite z naključno vrednostjo, tako da se dve zahtevi, podpisani v isti sekundi, še vedno razlikujeta. - Telo podpisane zahteve je lahko največ 64 KB, telo pa potrebuje
Content-Type: application/json.
Manjkajoči dogodek se vrača 401 missing_nostr_auth; ena, ki je slabo oblikovana, slabo podpisana, preveč stara ali za drugačen URL, metodo ali telo vrne
invalid_nostr_auth, z razlogom v sporočilu; ponovno uporabljen se vrne
nostr_auth_replayedPodpis se preveri, preden se telo prebere, in vsak naslov lahko ne uspe 30 krat na minuto (IPv6 naslov šteje kot celoto /64); potem dobi 429 s
Retry-After.
Brskalniki lahko te končne točke pokličejo samo iz lastnih spletnih mest Nymbota (https://nymbot.ai,
https://nymchat.app Stran na katerem koli drugem mestu ne dobi nobenih naslovov CORS nazaj, zato ne more prebrati tega, kar vrnejo.
Originin niso prizadeti.
Podpis potrebuje skrivni ključ vašega nimma (na nsec), ki nadzoruje vse: vašo identiteto, vašo zgodovino in vašo bilanco. Samo ga postavite v skript na stroju, ki mu zaupate, ga preberite iz okolja, namesto da bi ga zapisali v datoteko, in raje uporabite aplikacijo, ko lahko.
Ti pomočniki ustvarijo glavo. Kasnejši primeri na tej strani jih uporabljajo. Preberejo skrivni ključ v šestnem formatu iz NOSTR_SECRET_HEX; cURL ena uporablja
Nak orodje ukazne vrstice, ki vzame nsec ali hex ključ, in sha256sum za 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");
}
Povzetek računa
Kaj aplikacija API list prikazuje na vrhu: vaš javni ključ, oba ravnotežja, koliko ključev so aktivni (ni preklican ali potekel), in Samodejni top-up nastavitve ali
null če jih strežnik ne ponuja.
GET https://nymbot.ai/api/v1/account Potrebujejo a Podpisana zahteva.
Odgovor
{
"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());
Upravljanje ključev
Končne točke za seznamom ključev aplikacije. Vsi potrebujejo Podpisana zahtevaVsak ključ se vrne v tej obliki, s časi v ISO 8601 in zneski v sats:
Ključni predmet
{
"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 To je dovolj, da prepoznate ključ, vendar ga ne uporabite.Samo ključ se vrne le enkrat, ko je ustvarjen.
Seznam ključev
GET https://nymbot.ai/api/v1/keys je podpisal
| polje | Vrsta | Potrebno | Opis |
|---|---|---|---|
include_revoked | Boolean (poizvedba) | ne | Vključuje preklicane ključe. privzeto false. |
Odgovor
{ "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);
Izdelava ključa
POST https://nymbot.ai/api/v1/keys Podpis, vrnitev 201.
| polje | Vrsta | Potrebno | Opis |
|---|---|---|---|
name | String | ja | 1 do 40 znakov, ki se razlikujejo od drugih aktivnih ključev (ne upoštevajte primera). |
limit_sats | integer | ne | Izdatki v plačilnem načrtu, vsaj 1. pustite ga brez plačila. |
reset_period | String | ne | daily, weekly ali monthlyPotrebe limit_satsPustite ga ven za pokrov, ki se nikoli ne ponastavi. |
expire_at | String ali integer | ne | Ko ključ preneha delovati: ISO 8601 čas, ali milisekund od leta 1970. |
Odgovori na vprašanja (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"
}
}
| statusa | Kdaj |
|---|---|
400 | Manjkajoče ali preveliko ime; že uporabljeno ime (duplicate_name); omejitev, ki ni celo število vsaj 1; obdobje ponastavitve brez omejitve; iztekanje v preteklosti; neznano polje (unknown_parameter); ali 25 aktivnih ključev že (too_many_keys). |
429 | Več kot 60 ključev, ki jih ta nimm, ali 120 iz tega naslova, v eni uri (rate_limit_exceeded, z 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);
branje enega ključa
GET https://nymbot.ai/api/v1/keys/{id} je podpisal
Vrnitev {"data": {…}} s ključnim predmetom, ali 404
key_not_found če vaš ključ nima tega ID-ja.
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);
Spreminjanje ključa
PATCH https://nymbot.ai/api/v1/keys/{id} je podpisal
Pošljite katerokoli name, limit_sats, reset_period in
expire_at, z enakimi pravili kot pri izdelavi ključa. null Počisti polje: brez omejitve, brez ponastavitve, brez poteka. Če spremenite obdobje ponastavitve, se novo obdobje začne z ničlo.400 key_revoked• Vrnitev
{"data": {…}} z posodobljenim ključnim predmetom.
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);
Preklic ključa
DELETE https://nymbot.ai/api/v1/keys/{id} je podpisal
Zaustavite ključ naenkrat, za dobro. To ostane na seznamu s revoked_at postavljen, in ga je mogoče videti z include_revoked=truePreklic ključa, ki je že preklican, odgovori na enak način. Le zadnjih 50 preklicanih ključev je ohranjenih; starejši ključi so izbrisani, ko je preklican še en ključ.
Odgovor
{ "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 avto-top-up predvajanje
Povežite denarnico Lightning z aplikacijo Nostr Wallet Connect in Nymbot vzpostavi ravnovesje sam po sebi, ko poraba API teče nizko. Podpisana zahteva.
Kako deluje: ko se zahteva API zaračuna na stanje, ki ste ga izbrali za gledanje, če je to stanje padlo pod prag, Nymbot izda račun za vaš znesek, prosi vašo denarnico, da ga plača, in doda kredit. To se poveča največ enkrat vsakih 5 minut za vsak nim in ravnotežje, tako da izbruh zahtev ne more izprazniti denarnice. Poraba v aplikacijah ga ne sproži. Čas in velikost zadnjega top-up in zadnje napake sta v nastavitvah; če je plačilo šlo skozi po napaki, preverite svoj račun z Stanje top-up kreditov za to.
Nymbot shranjuje šifrirano in jo uporablja samo za plačilo lastnih računov, vendar vzpostavi povezavo samo za to, s proračunom za porabo v denarnici, tako da je največ, kar bi lahko kdaj plačal, številka, ki ste jo izbrali. denarnica mora podpirati pay_invoice.
Povežite denarnico
POST https://nymbot.ai/api/v1/nwc-auto-topup/connect je podpisal
| polje | Vrsta | Potrebno | Opis |
|---|---|---|---|
nwc_url | String | ja | Vtičnica za povezavo, ki se začne nostr+walletconnect://Nymbot prosi za denarnico get_info preden ga shranite in shranite šifrirano. |
threshold_sats | integer | ja | Na vrhu, ko je ravnovesje padlo pod te številne cene. |
topup_sats | integer | ja | Koliko je treba vsakič dodati. 1000 do 1.000.000 sats. |
tier | String | ne | pro (odvisno od dolžnosti) ali standard: ravnovesje za opazovanje in zgoraj. |
Odgovor
{
"data": {
"connected": true,
"threshold_sats": 5000,
"topup_sats": 20000,
"tier": "pro",
"last_topup_at": null,
"last_topup_sats": null,
"last_error": null
}
}
| statusa | Kdaj |
|---|---|
400 | Ni povezave vrstice (invalid_nwc_url); denarnica ni odgovorila na svoj prenos (nwc_unreachable) ali zavrnil preverjanje (nwc_rejected); povezava ne more plačati računov (nwc_missing_permissionali znesek, ki presega omejitve. |
501 | Za ta strežnik niso vklopljeni samodejni top-ups (nwc_unavailableEnako velja za druge dve končni točki. |
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());
branje nastavitev
GET https://nymbot.ai/api/v1/nwc-auto-topup je podpisal
Vrne isti predmet kot povezavo, z connected: false in druga polja
null ko ni povezanega denarnice. Povezava sama ni nikoli vrnjena.
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());
odklonitev
DELETE https://nymbot.ai/api/v1/nwc-auto-topup/connection je podpisal
Izbriše shranjeno vrstico povezave. Ni več top-upov. Da bi bili prepričani, lahko preklicate tudi povezavo v denarnici.
Odgovor
{ "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());
Plačilo na zahtevo brez ključa
Končne točke s fiksno ceno lahko plačate za eno zahtevo naenkrat preko Lightning, brez ključa, brez računa in brez ravnotežja: POST /images/generations, POST /images/edits,
POST /videos, POST /audio/speech, POST /audio/transcriptions,
POST /audio/translations in POST /embeddingsKlepet, Odgovori in Sporočila vedno potrebujejo ključ. Zahteva, ki nosi ključ, se obračuna na stanje kot običajno; pretok plačil se začne le, če ni poslan ključ.
Nymbot govori dve različici iste ideje, iz enega backend: Lightning Labs'
š402 (tudi pod njegovim starim imenom, LSAT) in osnutek IETF
plačilo HTTP preverjanje pristnosti s lightning Metoda in
charge Uporabite vse, kar vaš kupec razume.
Plačilo brez ključa je na voljo le, če API_L402_SECRET vsebuje vsaj 32 naključnih bajtov, kot je hex (64 znakov) ali base64 (44). openssl rand -hex 32Krajša ali ugibljiva vrednost izklopi funkcijo in zabeleži, zakaj. API_L402_SECRET_PREVIOUS za en dan: poverilnice, URL-ji stanja in izzivi, opravljeni pod njim, še naprej delujejo, dokler ne potečejo.
Izziv
Pošljite zahtevo z NE Authorization če je veljavna, se nič ne izvaja in dobite 402 Payment Required z računom za točno tisto, kar zahteva stroške: enako ceno bi ključ plačal, pretvoril na 10 sats standardni kredit ali 100 sats Pro kredit in zaokrožil do celotnega sat (vsaj 1 sat, in vsaj 0.05 kreditni minimum). WWW-Authenticate Izzivi za isti račun:
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 }
}
plačila request parameter je base64url JSON:
{"amount":"237","currency":"sat","methodDetails":{"invoice":"lnbc...","network":"mainnet","paymentHash":"..."}}.
Izziv je vezan na končno točko, na Content-Type (njegov tip medija in, za več delov, njegova meja) in na SHA-256 točnega telesa bajtov, ki ste jih poslali, in traja 15 minut. identična Ponovno vprašanje: enako
Content-Type in enake JSON bajte ali za večdelne končne točke (/images/edits, /audio/transcriptions, /audio/translationsVečina knjižnic HTTP izbere novo mejo vsakič, ko kodirajo obrazec, zato ga enkrat kodirajte in pošljite te bajte dvakrat.
Vsak naslov lahko zahteva 30 izzivov na minuto (IPv6 naslov šteje kot celoten /64). Zahteve, katerih naslov ni znan, delijo strožje 10 na minuto, in obstaja splošna omejitev na izzive Nymbot težave na vseh naslovih; zahteva zavrnjena pred izzivom (na primer s telesom, ki ni veljaven JSON) ne šteje proti njej. 429 s Retry-AfterPlačane končne točke, ki se kličejo brez ključa ali pooblastila, štejejo tudi do splošne omejitve 120 nepooblaščenih zahtevkov na minuto na naslov. Content-Type Ni pa application/json (ali pa
multipart/form-data za naložbe) je zavrnjen z 415 Nikoli ne dobiš računa.
Vdelave so cenjene na podlagi ocene žetonov v vnosu, z 1,5-kratno maržo, saj je dejansko število znano šele pozneje. Vrnite token.
Pošiljanje plačila
Plačajte račun s katerim koli Lightning denarnico. Denarnica vam daje predogled, 64 šesterih znakov. Nato pošljite isto zahtevo z enim od teh:
| sheme | Headerji |
|---|---|
| š402 | Authorization: L402 <macaroon>:<preimage> (LSAT deluje tudi |
| plačilo | Authorization: Payment <base64url JSON>, kjer je JSON {"challenge": {every parameter of the challenge, as sent}, "payload": {"preimage": "<hex>"}} |
Plačano povpraševanje odgovarja točno tako, kot je odgovorjeno s ključem, razen, da nymbot
Objekt nima polja ravnotežja: {"payment": "l402", "tier": "pro", "paid_sats": 237,
"charged_sats": 237}In ni nobenega X-Nymbot-Balance-Sats zahtevo, plačano s plačilno shemo, prejme tudi Payment-Receipt glavo (base64url JSON z id izziv, plačilni hash kot reference, status in
timestampPlačane zahteve niso vezane na noben nim, zato se ne pojavijo v zgodovini poizvedb.
| statusa | Kdaj |
|---|---|
402 payment_already_used | Vsako plačilo plača za eno zahtevo. odgovor je nov izziv za to zahtevo, tako da stranka, ki predpomni svoje zadnje poverilnice (kot lnget Pa še enkrat, samo še enkrat. |
402 payment_mismatch | Izdajalec je bil dodeljen za drugo končno točko, Content-Type ali telo, ali plača manj, kot je ta zahteva zdaj stane. nov izziv za to zahtevo prihaja z njim; če je bilo plačilo premajhno, se tisto, kar ste plačali, vrne kot Vrnite token (refund_token in refund_sats v svojem telesu). |
402 payment_expired | Od izziva je minilo več kot 15 minut. Z njim prihaja nov izziv. Če predogled prikazuje, da ste plačali, se to, kar ste plačali, vrne kot izziv. Vrnite token (refund_token in refund_sats v telesu), enkrat; potem se kredencial uporabi. |
401 invalid_preimage | Predogled ne hash na plačilni hash računa. plačilo se ne porabi. |
401 invalid_payment_credential | Poverilnica je nepravilno oblikovana, je bila spremenjena po tem, ko jo je izdal Nymbot, ali imenuje plačilni hash Nymbot ni nikoli izdal računa. |
429 rate_limit_exceeded | Več kot 30 poverilnic ali ključev, ki jih ni bilo mogoče preveriti, je prišlo s tega naslova v eni minuti, ali pa je bil en token za vračilo poslan več kot 60-krat v eni minuti. 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"));
Stranke so zgrajene na mppx z metodo Lightning sami obravnavajo izziv Plačila; pokažite jih na končno točko in pustite, da plačajo.
Video posnetki
Plačana je POST /videos Odgovori 202 kot ključavnica, plus a
status_url: GET To je podpisano in deluje 24 ur, dokler je delo ohranjeno.
{
"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..."
}
}
Ohranite jih refund_token iz tega odgovora: prikazano je samo tukaj. To je prazno, medtem ko je videoposnetek prikazan (GET /api/v1/l402/refunds Odgovori "status": "pending"); če prikaz ne uspe brez obračuna, plačilo pristane na njem.
refund_sats za povrnjeno delo, vendar nikoli žetona, tako da skupna raba URL stanja ne deli povračila.
Povračilo
Če plačana zahteva ne uspe in ponudnik zaračuna Nymbot za poskus, se plačilo ohrani in napaka pravi tako, z charged_sats, točno tako kot za ključno zahtevo. Če ne uspe brez zaračunavanja, napaka prinaša Vrnite token Vredno je, kar ste plačali:
{
"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"
}
}
Neuporabljeni deli se vrnejo na enak način: če ste zahtevali dve sliki in ena ni bila obračunana, je uspešen odgovor nymbot predmet nosi token za vračilo za manjkajočega; transkripcija, katere dolžine ni bilo mogoče predhodno prebrati, je cenjena za najdaljšo datoteko (nikoli več kot 30 minut), in razlika do dejanske dolžine se vrne kot token za vračilo; če se izkaže, da je daljša od 30 minut, se zavrne z 413
in celotno plačilo se vrne. Vdelave vrnejo tisto, kar je ocena zadržala. Neuspešen videoposnetek vrne žeton, ki ga je poslala.
Token za vračilo denarja je naključna 256-bitna koda. Nymbot shrani samo svoj hash in poteče po 30 dneh.
- Plačajte z njim. Pošlji
Authorization: Bearer REFUND-…na kateri koli od zgoraj navedenih končnih točk (OpenAI SDK jo vzame kot API ključ).refund_token_satsV nanymbotpredmet). žeton, ki je vreden manj kot odgovor na zahtevo402refund_insufficientNeizpolnjena napaka postavi sats nazaj na isti žeton. - Preverite ga
GET /api/v1/l402/refundsz istim naslovom se vrne{"sats": 237, "status": "open", "expires_at": "..."}. - En token se lahko uporabi največ 60 krat na minuto.
- Premaknite ga v nym. Vstavite ga v Privoščite darilo v aplikaciji Nymbot ali klic
POST /api/v1/l402/refunds/redeemz a Podpisana zahteva in{"refund_token": "REFUND-...", "balance": "standard"}(ali pa"pro"Celotni krediti gredo v stanje (10 sats vsak na standard, 100 na Pro); stave, ki ne naredijo celotnega kredita na žetonu za zahteve 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"
Odgovor
{ "data": { "credited": 23, "tier": "standard", "balance_credits": 123, "remaining_sats": 7 } }